3
#include <stdio.h>
int main(void)
{
    printf("%d", sizeof(signed int) > -1);
    return 0;
}

the result is 0 (FALSE). how can it be? Im using 64bit ubuntu linux so the result should be (4 > -1) => 1 => True.

zwol
  • 135,547
  • 38
  • 252
  • 361
Jah
  • 1,019
  • 1
  • 11
  • 25
  • as far as I know signed int and int are the same size of 4. Sizeof also depends on the compiler you use but you shouldn't be having a problem... hmmm. – Serguei Fedorov Apr 15 '12 at 19:30
  • 1
    `signed int`, `int`, and `unsigned int` are always the same size, but that size is not necessarily 4. However, the type of the result of `sizeof` is `size_t`. All sane ABIs make `size_t` the same size as `unsigned long`, which may or may not be the same size as `unsigned int` (it cannot be *smaller*, but it may well be bigger). – zwol Apr 15 '12 at 20:01

3 Answers3

10

Thing is the sizeof operator returns an unsigned quantity (size_t). So the comparison promotes -1 to unsigned, which makes it looks like a really big number.

You can try:

printf("%d", ((int)sizeof(signed int)) > -1);
cnicutar
  • 178,505
  • 25
  • 365
  • 392
8

sizeof(signed int) has type size_t, which is an unsigned type. When you make a comparison between a signed and an unsigned value [and the unsigned value's type is at least as large as the signed value's type], the signed value is converted to unsigned before the comparison. This conversion causes -1 to become the largest possible value of the unsigned type. In other words, it is as if you wrote

#include <limits.h>
/* ... */
printf("%d", sizeof(signed int) > SIZE_MAX);

You can make gcc warn when you make this mistake, but it's not on by default or even in -Wall: you need -Wextra or more specifically -Wsign-compare. (This warning can produce a great many false positives, but I think it's useful to turn on for new code.)

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 2
    It has nothing to do with two's complement. `(size_t)-1 == SIZE_MAX`. – Alok Singhal Apr 15 '12 at 19:46
  • 2
    Technically, it isn't actually true that signed is *always* promoted to unsigned even when one operand *is* unsigned, see 6.3.1.8 (1) where this happens only if the signed type was not also larger and able to represent all the possible values of a (possibly smaller) unsigned operand. – DigitalRoss Apr 15 '12 at 19:50
  • @DigitalRoss Quite right, corrected. – zwol Apr 15 '12 at 19:54
  • @Alok ... I coulda sworn signed-to-unsigned conversion theoretically didn't behave the same way on ones-complement or sign-and-magnitude machines, but you're right. (C99 6.3.1.3p2) Not that it matters anymore, considering how long it's been since anyone's manufactured a CPU that wasn't twos-complement for integers. – zwol Apr 15 '12 at 19:58
  • @Zack, you're right. I just wanted to be nit-picky. – Alok Singhal Apr 15 '12 at 20:08
5

The Integer Promotions

There are many implicit conversions in C, and it's helpful specifically to understand what are called the "usual arithmetic conversions", which include what are called the integer promotions.1

The actual rules are a bit complex, but, simplified, all scalar types are automatically converted when an operator has operands of different types. The conversion first takes the operand of lower rank and converts it to the type of the higher rank. Then, if only one operand is signed it is converted to unsigned unless the operand with signed type was larger and could have represented all of the unsigned type's values. That's not the case with your example because size_t is almost always as large or larger than int.

Finally, on almost all machines, -1 has all the bits set, making it a very large number when taken as unsigned.


1. ISO/IEC 9899:1999 ("C99") 6.3 Conversions

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • Last paragraph is irrelevant. Promotions (and all conversions in C) are *value* conversions, not reinterpretations of the representation. -1 converted to an unsigned type is **always** the largest value in that type, irrespective of the machine. – R.. GitHub STOP HELPING ICE Apr 15 '12 at 20:32
  • Technically true, C99 6.3.1.3(2), but that's a change from dmr and K&R that happens to be exactly equivalent to reinterpretation, for two's complement machines. One wonders what an oddball machine would actually do. – DigitalRoss Apr 15 '12 at 20:50
  • The "change" (from dealing with representations to values) happened when C was first standardized, but I believe the only change was in the way it was specified, not the behavior. As far as I know, there never were any pre-standardization, non-twos-complement C implementations, and the whole idea of allowing non-twos-complement was a nonsensical invention of the committee... – R.. GitHub STOP HELPING ICE Apr 15 '12 at 21:13