3
#include <stdio.h>

int main()
{
    printf("%zu\n", sizeof(-2147483648));
    printf("%zu\n", sizeof(-2147483647-1));
    return 0;
}

The above code gives as output (gcc):

8  
4  

Why is -2147483648 automatically promoted to long in 1st printf even when it can fit in an int?

Also, I tried the same in MinGW and it gives the output:

4  
4  

Can someone please explain what's going on?

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
avmohan
  • 1,820
  • 3
  • 20
  • 39
  • MinGW isn't a compiler; I guess you mean gcc built for MinGW . – M.M Sep 04 '14 at 06:30
  • 1
    It's important to remember that the sizes of `int` and `long` are implementation-defined. `int` must be at least 16 bits wide, `long` must be at least 32 bits wide, and `long` must be at least as wide as `int`. Incidentally, the correct format for printing a `size_t` value is `%zu`. – Keith Thompson Sep 04 '14 at 06:37
  • The proper way to print values of type `size_t` is with `%zu`, by the way. – unwind Sep 04 '14 at 07:05

2 Answers2

10

The number 2147483648 is too large to fit into an int, so it is promoted to long.

Then, after the number has already been promoted to long, its negative is computed, yielding -2147483648.

If you're curious, you can look at limits.h. On my platform, which uses glibc,

#  define INT_MIN       (-INT_MAX - 1)
#  define INT_MAX       2147483647

On MinGW, sizeof(long) == 4, so promotion to long won't cut it. According to the C11 standard, the value must be promoted to long long. This doesn't happen, probably because your MinGW compiler is defaulting to C90 or earlier.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
7

-2147483648 is the integral constant expression 2147483648 with the unary minus operator applied.

Your systems both appear to have int and long as 32-bit, and long long as 64-bit.

Since the base-10 constant 2147483648 cannot fit in long int, in C99 it has type long long int. However, C90 did not have this type, so in C90 it has type unsigned long int.

A common workaround for this issue is, as you say, to write -2147483647 - 1. You will probably see something similar as the definition of INT_MIN if you check your system's limits.h .

Regarding the output 4, this suggests that on your MinGW system you are using C90 and on your other system you are using C99 or C11 (or C++, or GCC extensions).

M.M
  • 138,810
  • 21
  • 208
  • 365
  • +1 LSNED C89/90 "The type of an integer constant is the first of the corresponding list in which its value can be represented. Unsuffixed decimal: `int, long int, unsigned long int`". C11 `int, long int, long long int`. With current C, an unsuffixed decimal is never `unsigned anything`. Not so with earlier C. – chux - Reinstate Monica Sep 04 '14 at 16:29