1

Given that code :

int main(void) {
    long x = -1;
    if (x < sizeof(x)) {
        printf("OK\n");
    }
    else {
        printf("Not Ok\n");
    }
    return 0;
}  

Prints:

Not Ok

I have read about usual arithmetic conversions, and from what i understood that if we have a comparison between two operands with different data types, the compiler invokes a data coercion on the operand which is narrower than the other operand, which will convert the the sizeof(x) into unsigned int to match the other operand, any thoughts?

Aside question: I tried to do casting size(x) as int in the comparison expression as:

if(x < (int) size(x))

It prints Ok, which I find very strange!

Stargateur
  • 24,473
  • 8
  • 65
  • 91
Mosaaleb
  • 1,028
  • 1
  • 9
  • 23
  • 3
    C is not C++ is not C, tag only one language. – Stargateur Jul 01 '17 at 08:43
  • Explain more about what u wanna do with that code – moh89 Jul 01 '17 at 08:48
  • The first should rise a warning from your compiler. Why do you think that the second has a strange behavior? – Bob__ Jul 01 '17 at 08:50
  • 3
    At the risk of sounding self-serving, [you may find this an interesting read](https://stackoverflow.com/questions/13600991/why-is-a-negative-int-greater-than-unsigned-int) – WhozCraig Jul 01 '17 at 08:51
  • To be clear the trap here, as you despite the question seem to have noted yourself, is that the C language does not promote to a wider type when mixing `signed` and `unsigned` expressions of the same size. Despite that this may be unsafe as in the code above. One might argue that this should be done if possible, or issue a compile-time error. That is not how the language is defined however and good compilers issue warnings as a substitute. – doynax Jul 01 '17 at 08:52
  • 2
    @WhozCraig Why not mark as dupe as that one? That is the answer. – Sourav Ghosh Jul 01 '17 at 08:54
  • To expand on some of the above comments, `-1` when converted to an unsigned value is a very large number. It will most definitely not be less than `4` or `8` (which are the common sizes of `long`). – Some programmer dude Jul 01 '17 at 08:55
  • @Someprogrammerdude Yes, and size_t has the same size as long as 8 bytes – Mosaaleb Jul 01 '17 at 08:55
  • 1
    @WhozCraig and please, no one's gonna charge you with _self-serving_ :) – Sourav Ghosh Jul 01 '17 at 08:55
  • @Bob__ I suppose from the comparison expression `sizeof(x)` is treated as int, and it prints `Not Ok`, and when i tried to cast it to `int`, the program prints `Ok` – Mosaaleb Jul 01 '17 at 08:59
  • Maybe you should also check out [`sizeof`](http://en.cppreference.com/w/c/language/sizeof) and [`size_t`](http://en.cppreference.com/w/c/types/size_t). – Bob__ Jul 01 '17 at 09:05

1 Answers1

1

You should never compare a signed number to an unsigned number. Add a compiler switch to warn you about this.

Here, in your case, x will be converted to unsigned, -1 becomes SIZE_MAX (the largest number a that std::size_t can hold). It is because sizeof returns an unsigned number (it returns std::size_t, which is unsigned)

The other thing that could happen, but don't happen in practice is that if sizeof(long)>sizeof(std::size_t) then sizeof(x) would be converted to long, so your program would print OK.

geza
  • 28,403
  • 6
  • 61
  • 135