Velocity Reviews > condition true or false? -> (-1 < sizeof("test"))

# condition true or false? -> (-1 < sizeof("test"))

Tim Rentsch
Guest
Posts: n/a

 05-17-2012
Eric Sosman <(E-Mail Removed)> writes:

> On 5/17/2012 4:40 AM, John Reye wrote:
>> Hello,
>>
>> please can someone explain why
>> (-1< sizeof("test"))
>> is false.

>
> [snip]
>
> Aside: I suppose that on a perverse implementation the
> outcome might be different. If (size_t)-1 is mathematically
> no greater than INT_MAX the conversion would go the other way.
> The size_t would convert to an int before the comparison and
> you'd have:
>
> if ( -1 < (int)sizeof("test") )
>
> I've never heard of an implementation where size_t is so
> narrow, and I'm not 100% sure it would be conforming -- but
> I'm not 100% sure it would be forbidden, either.

More specifically, if the integer conversion rank of size_t is
less than the integer conversion rank of int, and if the two
limits involved satisfy SIZE_MAX <= INT_MAX, then expressions
like '-1 < sizeof x' can be true. For size_t, the Standard
requires only that it be an unsigned integer type and that its
maximum value be at least 65535. So, it is certainly possible
for an implementation to satisfy the listed conditions and
still be conforming.

Eric Sosman
Guest
Posts: n/a

 05-18-2012
On 5/17/2012 8:05 AM, BartC wrote:
> "Ben Bacarisse" <(E-Mail Removed)> wrote in message
>> "BartC" <(E-Mail Removed)> writes:

>
>>> (Presumably an integer literal such as "4"
>>> is assumed to be signed? Having it as unsigned would be more
>>> intuitive, as
>>> it would be impossible for it to be negative.)

>>
>> But that would turn x < 4 into an unsigned comparison. Worse, -1 would
>> always be unsigned (and large).

>
> 1 would be unsigned.
>
> -1, assuming constant folding by the compiler, would be equivalent to a
> signed integer literal of "-1".

There is no such thing as a "signed integer literal of `-1'."

More exactly, there is no such thing as an "integer literal."
Of course, the "integer-constant" exists and is well-defined, but
even so `-1' is not an "integer-constant."

Quiz question: Write a constant whose type is `int' and whose
value is negative one, without resorting to implementation-defined
or undefined or locale-specific behavior. (Hint: There is at least
one completely portable way to do this.)

> (If not, then it remains the negation of unsigned 1, performed at
> runtime. For this purpose, negating an unsigned value would need to be
> allowed, and I can't see a problem with that, except the usual overflow
> issues).

Negation of unsigned 1 (which can be written `-1u') is already
defined in C, although there are implementation-defined aspects.
In particular, there are no "overflow issues," usual or otherwise.

it would be far more credible if there were evidence that you knew
some C in the first place. Go, and correct that deficiency, and
you will receive more respectful attention than you now merit.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)d

Eric Sosman
Guest
Posts: n/a

 05-18-2012
On 5/17/2012 10:04 AM, James Kuyper wrote:
> On 05/17/2012 07:38 AM, Eric Sosman wrote:
> ...
>> outcome might be different. If (size_t)-1 is mathematically
>> no greater than INT_MAX the conversion would go the other way.
>> The size_t would convert to an int before the comparison and
>> you'd have:
>>
>> if ( -1< (int)sizeof("test") )
>>
>> I've never heard of an implementation where size_t is so
>> narrow, and I'm not 100% sure it would be conforming -- but
>> I'm not 100% sure it would be forbidden, either.

>
> Can you give a justification for your doubts about whether such an
> implementation could be conforming?

Just a reluctance to assert the contradiction, and then come
a cropper when a language lawyer combines the fourth sentence of
6.2.6.3p5 with the second of 5.1.3.2p4 and the entirety of 4.4 to
show that one or the other conclusion is definite.

In short, laziness.

> The lower limit for SIZE_MAX is 65535, and there's no upper limit for
> INT_MAX, so I don't see why an implementation where SIZE_MAX< INT_MAX
> could not be fully conforming.

Nor do I, but "meddle not in the affairs of Standards, for they
are subtle and quick to anger." I have in the past asserted "the
Standard requires" or "the Standard forbids" only to be shown wrong,
so I now try to refrain from such assertions when they're not central
to the matter at hand. Trying to avoid unforced errors, if you like.

--
Eric Sosman
(E-Mail Removed)d

Kaz Kylheku
Guest
Posts: n/a

 05-18-2012
On 2012-05-18, Eric Sosman <(E-Mail Removed)> wrote:
> Quiz question: Write a constant whose type is `int' and whose
> value is negative one, without resorting to implementation-defined
> or undefined or locale-specific behavior. (Hint: There is at least
> one completely portable way to do this.)

You didn't say "integer constant". In the grammar, a constant
generates one of four productions, one of which is "enumeration constant".

Hence:

enum x { y = -1; };

y; // <- constant, type int, value -1.

Eric Sosman
Guest
Posts: n/a

 05-18-2012
On 5/17/2012 10:48 PM, Kaz Kylheku wrote:
> On 2012-05-18, Eric Sosman<(E-Mail Removed)> wrote:
>> Quiz question: Write a constant whose type is `int' and whose
>> value is negative one, without resorting to implementation-defined
>> or undefined or locale-specific behavior. (Hint: There is at least
>> one completely portable way to do this.)

>
> You didn't say "integer constant".

Indeed, I did not. That's what's known as a Clue.

> In the grammar, a constant
> generates one of four productions, one of which is "enumeration constant".

Give the man a cigar!

As far as I know, an enum named constant is the only portable
way to produce a negative integer constant in C. On some systems,
constructs like '£' or 'pound' or L'sterling' might be negative
constants, but they're non-portable. (I believe that '\377' must
be positive, although some pre-Standard compilers I dimly recall

--
Eric Sosman
(E-Mail Removed)d

BartC
Guest
Posts: n/a

 05-18-2012
"Eric Sosman" <(E-Mail Removed)> wrote in message
news:jp45cv\$l0q\$(E-Mail Removed)...
> On 5/17/2012 8:05 AM, BartC wrote:

>> (If not, then it remains the negation of unsigned 1, performed at
>> runtime. For this purpose, negating an unsigned value would need to be
>> allowed, and I can't see a problem with that, except the usual overflow
>> issues).

> Negation of unsigned 1 (which can be written `-1u') is already
> defined in C, although there are implementation-defined aspects.
> In particular, there are no "overflow issues," usual or otherwise.

That's true; the value of -3000000000u on my 32-bit C is well-defined;
completely wrong, but well-defined according to the Standard.

Actually only lcc-win32, out of my handful of C compilers, bothers to tell
me that that expression has an overflow.

> it would be far more credible if there were evidence that you knew
> some C in the first place. Go, and correct that deficiency, and
> you will receive more respectful attention than you now merit.

The 'whinings' were to do with being dependent on compiler options for
figuring why programs like this:

unsigned int a=4;
signed int b=-2;

printf("%u<%d = %d\n", a, b, a<b);
printf("%d<%d = %d\n", 4, b, 4<b);
printf("%u<%d = %d\n", a, -2, a<-2);
printf("%d<%d = %d\n", 4, -2, 4<-2);

(notice the integer literals, or constants, or whatever you like to call
them today, have been correctly displayed as signed values) produce output
like this:

4<-2 = 1
4<-2 = 0
4<-2 = 1
4<-2 = 0

You don't need to know any C, or any language, for it to raise eyebrows. And
as it happened, I had trouble getting any of my four compilers to give any
warning, until someone told me to try -Wextra on gcc.

> it would be far more credible if there were evidence that you knew
> some C in the first place.

How much C does someone need to know, to complain about -1 being silently
converted to something like 4294967295?

A lot of my 'whinings' are backed up by people who know the language
inside-out. And although nothing can be done because the Standard is always
right, and the language is apparently set in stone, at least discussion
about various pitfalls can increase awareness.

--
Bartc

--
Bartc

James Kuyper
Guest
Posts: n/a

 05-18-2012
On 05/18/2012 07:04 AM, BartC wrote:
> "Eric Sosman" <(E-Mail Removed)> wrote in message
> news:jp45cv\$l0q\$(E-Mail Removed)...
>> On 5/17/2012 8:05 AM, BartC wrote:

....
> That's true; the value of -3000000000u on my 32-bit C is well-defined;
> completely wrong, but well-defined according to the Standard.

The standard defines what "right" means in the context of C code. If
-3000000000u has the value which the standard says it must have, then it
is the right value, even if it's not the value you think the standard
should specify.

....
> unsigned int a=4;
> signed int b=-2;
>
> printf("%u<%d = %d\n", a, b, a<b);
> printf("%d<%d = %d\n", 4, b, 4<b);
> printf("%u<%d = %d\n", a, -2, a<-2);
> printf("%d<%d = %d\n", 4, -2, 4<-2);
>
> (notice the integer literals, or constants, or whatever you like to call
> them today, have been correctly displayed as signed values) produce output
> like this:
>
> 4<-2 = 1
> 4<-2 = 0
> 4<-2 = 1
> 4<-2 = 0
>
> You don't need to know any C, or any language, for it to raise eyebrows.

You're printing out the values of "b" or -2, rather than the values
which are being compared with "a". a<b does not compare the value of "a"
with the value of "b", it compares it with the value of (unsigned)b.
Similarly for a < -2. You need to know C to realize this fact. If you
print out the actual values being compared, you'll see nothing surprising.

>> it would be far more credible if there were evidence that you knew
>> some C in the first place.

>
> How much C does someone need to know, to complain about -1 being silently
> converted to something like 4294967295?

Not much; in fact, the less you know about C, the easier it is to feel
the need to complain about such things.

> A lot of my 'whinings' are backed up by people who know the language
> inside-out. And although nothing can be done because the Standard is always
> right, and the language is apparently set in stone, at least discussion
> about various pitfalls can increase awareness.

The language has not been set in stone; C2011 made a lot of changes.
However, this is a very fundamental feature of the language. The
doesn't provide one, complain to the compiler vendor. The C standard
could mandate a diagnostic only at the cost of rendering the behavior
undefined if the code is compiled and executed despite generation of
that diagnostic. Such a change would break a LOT of code, and would
therefore be unacceptable.
--
James Kuyper

Ben Bacarisse
Guest
Posts: n/a

 05-18-2012
"BartC" <(E-Mail Removed)> writes:

> "Eric Sosman" <(E-Mail Removed)> wrote in message
> news:jp45cv\$l0q\$(E-Mail Removed)...
>> On 5/17/2012 8:05 AM, BartC wrote:

>
>
>>> (If not, then it remains the negation of unsigned 1, performed at
>>> runtime. For this purpose, negating an unsigned value would need to be
>>> allowed, and I can't see a problem with that, except the usual overflow
>>> issues).

>
>> Negation of unsigned 1 (which can be written `-1u') is already
>> defined in C, although there are implementation-defined aspects.
>> In particular, there are no "overflow issues," usual or otherwise.

>
> That's true; the value of -3000000000u on my 32-bit C is well-defined;
> completely wrong, but well-defined according to the Standard.

Why is this wrong? Negation preserves the type of the operand which
makes it a closed operation on a group -- it's simple to explain and
mathematically justifiable. Why is your idea of what '-' should mean
for unsigned operands better than anyone else's?

> Actually only lcc-win32, out of my handful of C compilers, bothers to tell
> me that that expression has an overflow.

That's because there is none, but I am not just making a semantic point
about "wrap-around" vs. "overflow". I don't think a compiler should
warn about negating an unsigned value because it makes perfect sense --
both doing it and the result you get. Unsigned arithmetic in C is
arithmetic modulo 2^n, where n is the width of the unsigned type. This
is, in almost every case, exactly what I want it to be. I *want* the
arithmetic operators to have the meaning they do for unsigned integer
types. Singling out unary '-' would make it a mess.

Also, look at the way you expressed this. It sounds very dismissive.
Do you really think all those compiler writers simply thought "let's not
well-supported reasons for writing the compiler they did? There are
more kinds of arithmetic than are dreamt of in your philosophy.

>> it would be far more credible if there were evidence that you knew
>> some C in the first place. Go, and correct that deficiency, and
>> you will receive more respectful attention than you now merit.

>
> The 'whinings' were to do with being dependent on compiler options for
> figuring why programs like this:
>
> unsigned int a=4;
> signed int b=-2;
>
> printf("%u<%d = %d\n", a, b, a<b);
> printf("%d<%d = %d\n", 4, b, 4<b);
> printf("%u<%d = %d\n", a, -2, a<-2);
> printf("%d<%d = %d\n", 4, -2, 4<-2);
>
> (notice the integer literals, or constants, or whatever you like to call
> them today, have been correctly displayed as signed values) produce output
> like this:
>
> 4<-2 = 1
> 4<-2 = 0
> 4<-2 = 1
> 4<-2 = 0
>
> You don't need to know any C, or any language, for it to raise
> eyebrows.

No, but it helps. The same goes for all sorts of operations in all
programming languages. None of them are free of surprises for those not
in the know. Does C have more scope for surprise? Probably, but it's
not certain. Haskell, for example, has operators that are as close to
what you want as is possible, but you might find lots of other things

In all these complaints you don't present a cohesive alternative. C's
rules for determining a common type are (despite the presentation of
them in the standard) relatively simple. They stem from a design that
tries to keep close to most hardware can do without extra hidden costs.

> as it happened, I had trouble getting any of my four compilers to give any
> warning, until someone told me to try -Wextra on gcc.

That's another issue altogether. One of the first things I do when
using any compiler is to find out how to get it to tell me as much as
possible about my code. I always plan to shut it up later when I'm
more familiar with the language, but I rarely do.

>> it would be far more credible if there were evidence that you knew
>> some C in the first place.

>
> How much C does someone need to know, to complain about -1 being silently
> converted to something like 4294967295?

You are mixing issues again. C does not say the conversion must be
silent and most compilers will help you out here. If you don't like how
they do that, complain to the compiler writers.

As for what C does say, that in signed to unsigned comparisons -1 is
(usually) converted to unsigned, I think some understanding of C is
needed for the complaint to be taken seriously. I would only complain
about language feature X if I was pretty sure I knew why it was designed
that way (even if that turns out to be simply "the designer made a
mistake") and I could demonstrate a better design that meets the same
objectives. I am not saying that people who don't know C can't express
an opinion about it, but that's not the same as declaring a language
feature "wrong" or suggesting that it's obvious that it should be done
differently.

No hardware that I know can compare all signed and unsigned integers in
the way that you seem to want. Something has to give -- either more
code has to be generated or some surprising cases will occur.
Explaining what you want need not be a lot of work. You could just say
C should do it like X does it. Surely at least one programming language
as got integer arithmetic and comparison right as far as you are
concerned.

<snip>
--
Ben.

BartC
Guest
Posts: n/a

 05-18-2012
"Ben Bacarisse" <(E-Mail Removed)> wrote in message
news:0.2e9a0e60743c3a0379f8.20120518134552BST.87eh (E-Mail Removed)...

>> That's true; the value of -3000000000u on my 32-bit C is well-defined;
>> completely wrong, but well-defined according to the Standard.

>
> Why is this wrong? Negation preserves the type of the operand which
> makes it a closed operation on a group -- it's simple to explain and
> mathematically justifiable. Why is your idea of what '-' should mean
> for unsigned operands better than anyone else's?

My idea is that when you take a positive number, and negate it, that you
usually end up with a negative number! My apologies if that sounds too
far-fetched!

Translated into a language with a simple type system like C's, that would
imply that applying negation to an unsigned type, would necessarily need to
yield a signed result. Unless you apply a totally different meaning to
negation than is usually understood.

>> How much C does someone need to know, to complain about -1 being silently
>> converted to something like 4294967295?

>
> You are mixing issues again. C does not say the conversion must be
> silent and most compilers will help you out here. If you don't like how
> they do that, complain to the compiler writers.
>
> As for what C does say, that in signed to unsigned comparisons -1 is
> (usually) converted to unsigned, I think some understanding of C is
> needed for the complaint to be taken seriously. I would only complain
> about language feature X if I was pretty sure I knew why it was designed
> that way (even if that turns out to be simply "the designer made a
> mistake") and I could demonstrate a better design that meets the same
> objectives.

(I have a fledgling language and compiler, which while it doesn't do much at
present, can at least take:

println -3000000000

and output -3000000000. The type of 3000000000 is 32-bit unsigned. The type
of -3000000000 is 64-bit signed. I'm not interested in selling or making
available this language, but it's just serving here as an example of a
slightly different approach to doing things.)

> No hardware that I know can compare all signed and unsigned integers in
> the way that you seem to want. Something has to give -- either more
> code has to be generated or some surprising cases will occur.
> Explaining what you want need not be a lot of work. You could just say
> C should do it like X does it. Surely at least one programming language
> as got integer arithmetic and comparison right as far as you are
> concerned.

Hardware either does sign-less add/subtract, or offers signed/unsigned
multiply/divide. So it's mostly a language issue. Since this last has
already been sorted out for C, this is just for interest.

Using fixed-width types for operands and results, there are always going to
be some problems when doing arithmetic: values could overflow for example.
This is acceptable in this context; dealing properly with overflow can be
difficult, you might decide to leave it to a higher level language than
we're dealing with here. (And C decides that unsigned overflow isn't
overflow at all.)

But then you have mixed-signed arithmetic. The proper way to deal with this
is to convert both sides to a common type that can contain both kinds of
value. But this is not always practical (maybe there is no larger type), and
it can be inefficient. So we compromise by keeping the same width, not ideal
because you can't reliably convert one type to the other without possible
overflows. But ignoring overflow for the minute:

You're doing arithmetic between a number that can be negative, on a number
that is positive. The result of course could be negative or positive.
Naturally, you'd expect the result to be a signed type so that it could
accommodate both. But C decides the result is always going to be positive!

Taking 32-bit ints as an example: although there are always going to be
problems with overflows, at least using signed arithmetic, things will work
out if the signed operand is within roughly - 2 billion to 2 billion, the
unsigned one is within 0 to to 2 billion, and the result is within -2
billion to 2 billion. That will include the OP's -1<4 or -1<8 comparison in
addition to many, many ordinary everyday expressions.

But with unsigned arithmetic, both operands and result must lie within 0 to
2 billion, to give a sensible result. There's a strong chance of the wrong
result if *any* negative value, such as -1, is involved. Unless you are
lucky, for example by performing addition, and the result happens to be
positive.

(I did once ask for C's rationale for using unsigned mode for mixed
arithmetic, but I didn't get an answer that explained why.)

--
Bartc

Ben Bacarisse
Guest
Posts: n/a

 05-19-2012
"BartC" <(E-Mail Removed)> writes:

> "Ben Bacarisse" <(E-Mail Removed)> wrote in message
> news:0.2e9a0e60743c3a0379f8.20120518134552BST.87eh (E-Mail Removed)...
>
>>> That's true; the value of -3000000000u on my 32-bit C is well-defined;
>>> completely wrong, but well-defined according to the Standard.

>>
>> Why is this wrong? Negation preserves the type of the operand which
>> makes it a closed operation on a group -- it's simple to explain and
>> mathematically justifiable. Why is your idea of what '-' should mean
>> for unsigned operands better than anyone else's?

>
> My idea is that when you take a positive number, and negate it, that you
> usually end up with a negative number! My apologies if that sounds too
> far-fetched!

- is not negation, or at least not only negation. That symbol is used
in lots of contexts to mean all sorts of things. In C it means both
negation and "additive inverse" -- the latter being nothing more than
negation in a finite group. In unsigned arithmetic, the additive
inverse is not a negative number (so people shy away from calling it
negation).

The meaning you accept is the one that does not correspond to any usual
mathematical meaning. Signed negation can overflow, making it only an
approximation to the mathematical version. C's unsigned negation always
works and corresponds exactly to the mathematical notion on which it is
modeled.

> Translated into a language with a simple type system like C's, that would
> imply that applying negation to an unsigned type, would necessarily need to
> yield a signed result. Unless you apply a totally different meaning to
> negation than is usually understood.

I don't want to use programming languages that can only perform
operations as they are "usually understood". The "usual" meaning is
already covered by C's signed arithmetic, so C is adding something here.
I've used "scare quotes" because I'm not 100% sure what you mean by
usual. If it's statistical -- ask 100 people and give '-' only the
meaning the majority would expect -- I don't want that to be a factor in
the design of C.

>>> How much C does someone need to know, to complain about -1 being silently
>>> converted to something like 4294967295?

>>
>> You are mixing issues again. C does not say the conversion must be
>> silent and most compilers will help you out here. If you don't like how
>> they do that, complain to the compiler writers.
>>
>> As for what C does say, that in signed to unsigned comparisons -1 is
>> (usually) converted to unsigned, I think some understanding of C is
>> needed for the complaint to be taken seriously. I would only complain
>> about language feature X if I was pretty sure I knew why it was designed
>> that way (even if that turns out to be simply "the designer made a
>> mistake") and I could demonstrate a better design that meets the same
>> objectives.

>
> (I have a fledgling language and compiler, which while it doesn't do much at
> present, can at least take:
>
> println -3000000000
>
> and output -3000000000. The type of 3000000000 is 32-bit unsigned. The type
> of -3000000000 is 64-bit signed. I'm not interested in selling or making
> available this language, but it's just serving here as an example of a
> slightly different approach to doing things.)

That does not give me any clue about why you think C is "wrong". It
tells me what you've done in some language with no context. Does this

>> No hardware that I know can compare all signed and unsigned integers in
>> the way that you seem to want. Something has to give -- either more
>> code has to be generated or some surprising cases will occur.
>> Explaining what you want need not be a lot of work. You could just say
>> C should do it like X does it. Surely at least one programming language
>> as got integer arithmetic and comparison right as far as you are
>> concerned.

>
> Hardware either does sign-less add/subtract, or offers signed/unsigned
> multiply/divide. So it's mostly a language issue. Since this last has
> already been sorted out for C, this is just for interest.
>
> Using fixed-width types for operands and results, there are always going to
> be some problems when doing arithmetic: values could overflow for example.
> This is acceptable in this context; dealing properly with overflow can be
> difficult, you might decide to leave it to a higher level language than
> we're dealing with here. (And C decides that unsigned overflow isn't
> overflow at all.)

You brought up compares (well, the OP did but you extended the example)
and so I talked about compares. It would be simpler to stick to
explaining what C could do that's "better" whilst sticking to C's design
objectives. You've gone off to talk about arithmetic in general. What
do you think C could do with mixed-type compares?

> But then you have mixed-signed arithmetic. The proper way to deal with this
> is to convert both sides to a common type that can contain both kinds of
> value. But this is not always practical (maybe there is no larger type), and
> it can be inefficient. So we compromise by keeping the same width, not ideal
> because you can't reliably convert one type to the other without possible
> overflows. But ignoring overflow for the minute:
>
> You're doing arithmetic between a number that can be negative, on a number
> that is positive. The result of course could be negative or positive.
> Naturally, you'd expect the result to be a signed type so that it could
> accommodate both. But C decides the result is always going to be positive!
>
> Taking 32-bit ints as an example: although there are always going to be
> problems with overflows, at least using signed arithmetic, things will work
> out if the signed operand is within roughly - 2 billion to 2 billion, the
> unsigned one is within 0 to to 2 billion, and the result is within -2
> billion to 2 billion. That will include the OP's -1<4 or -1<8 comparison in
> addition to many, many ordinary everyday expressions.
>
> But with unsigned arithmetic, both operands and result must lie within 0 to
> 2 billion, to give a sensible result. There's a strong chance of the
> wrong result if *any* negative value, such as -1, is involved. Unless
> you are lucky, for example by performing addition, and the result
> happens to be positive.

Where is this going? I know all of the above. I disagree with some of
it (for example that C's unsigned arithmetic produces results that are
not sensible). None of it helps me to see why you think C is wrong.

> (I did once ask for C's rationale for using unsigned mode for mixed
> arithmetic, but I didn't get an answer that explained why.)

--
Ben.