1

Ok, trying to understand why the if statement below is false. I've turned it inside out and can't understand what is going on here.

#define SIZE (sizeof(arr)/sizeof(int))

int main(int argc, char** argv)
{
    int arr[] = {1,2,3,4,5,6,7,8};

    if ( -1 <= SIZE )
        printf( "true" );
    else
        printf( "false" );

    return 0;

}
Dave Black
  • 65
  • 8
  • 1
    A better macro would be `#define SIZE (sizeof(arr)/sizeof(*(arr)))` – Oliver Matthews Apr 11 '14 at 14:28
  • As far as I can tell, your program exhibits **implementation defined behavior**, depending on relative integer rank of `int` and `size_t`. I don't know any implementation with rank `int` > rank `size_t`, which is neccessary to print `true` in your example. – Deduplicator Apr 11 '14 at 14:36
  • 1
    You can use no-prototype style, but then you are in pre-C99 backwards-compatibility mode. You really don't want to go there. Use `int main(int argc, char** argv)`, `int main(void)` or compatible. – Deduplicator Apr 11 '14 at 14:51
  • This is a duplicate of [Why is this happening with the sizeof operator?](http://stackoverflow.com/questions/22047158/why-is-this-happening-with-the-sizeof-operator) – Shafik Yaghmour Jul 01 '14 at 02:13

1 Answers1

12

It prints false because of signed/unsigned mismatch in the comparison.

The result of sizeof is a size_t value, which is unsigned. When the int value -1 is compared to that, the integer is interpreteted as a very large unsigned value.

The C99 draft standard expresses this like so:

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Here, the size_t is at least unsigned int which makes it rank equal to or out-rank int, and thus cause the int to be converted to size_t.

Also, main() really does return int, I don't understand why you edited that out.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
unwind
  • 391,730
  • 64
  • 469
  • 606
  • So, the compiler is converting the int literal to unsigned, same as size_t? – Dave Black Apr 11 '14 at 14:26
  • `(unsigned int)-1` ends up usually as `0xFFFFFFFF` – Agent_L Apr 11 '14 at 14:29
  • Is there any normative text guaranteeing `-1` will be converted to `((size_t)-1)` instead of `SIZE` to `((int)SIZE)`? – Deduplicator Apr 11 '14 at 14:30
  • 1
    @DaveBlack No, the *literal* is never converted, it's just the value of evaluating that literal at that particular place in the code. – unwind Apr 11 '14 at 14:30
  • @Deduplicator I think so, that's what the rank talk I added is about. – unwind Apr 11 '14 at 14:30
  • 1
    @Agent_L as I explained in the answer linked in my comment it will always be UMAX. – Shafik Yaghmour Apr 11 '14 at 14:30
  • As far as I can say, it is not. `size_t` may have higher, lower or equal rank to `int`. So it is not guaranteed. – Deduplicator Apr 11 '14 at 14:33
  • You should not think too much about "conversions of value". Both signed and unsigned ints are just few bytes in the memory. Tt's how compiler treats them at given time. This happens here, the -1 gets rather "interpreted as" than "converted to" unsigned. – Agent_L Apr 11 '14 at 14:35
  • @Agent_L: That's a conversion, even if you tell yourself it is only an interpretation. – Deduplicator Apr 11 '14 at 14:37
  • i got 4294967295d, 0xFFFFFFFF. yup. – Dave Black Apr 11 '14 at 14:38
  • @unwind: `unsigned` or bigger unsigned type. You really cannot say from context. – Deduplicator Apr 11 '14 at 14:39
  • @ShafikYaghmour: Which is enough to make the literal -1 convert to unsigned. – Deduplicator Apr 11 '14 at 14:42
  • @Deduplicator : That's mere interpretation, even if language spec calls it a conversion. The spec is very old and unfortunate phrasing confuses ppl who came from higher lvl languages, where variables actually carry their own type and conversion is entirely different process than just reinterpretation. – Agent_L Apr 11 '14 at 14:45
  • 2
    @DaveBlack That is not up to you to decide, `main()` *must* return `int`, by definition. If you're doing something else, you're not programming in standard-compliant C. – unwind Apr 11 '14 at 14:46