The type of the constant 1
is int, so technically a type conversion will be done but it'll be done at compile time and nothing is lost.
However, consider the more interesting example of:
int main(void)
{
long long i = -2147483648;
long long j = -2147483647 - 1;
printf( " i is %lld, j is %lld\n", i, j);
return(0);
}
I get the following results from various compilers:
MSCV 9 (Version 15.00.21022.08):
i is 2147483648, j is -2147483648
GCC (3.4.5):
i is -2147483648, j is 0
Comeau (4.3.10.1):
i is 2147483648, j is -2147483648
Digital Mars:
i is -2147483648, j is -2147483648
I'm not sure yet how to account for the differences. It could be one or more of:
- compiler bugs
- C90 vs. C99 rules in operand promotion ("
long long
" support is C99, but some of these compilers might be compiling for C90 with "long long
" as an extension)
- implementation defined behavior
- undefined behavior
FWIW, the behavior of MSVC and Comeau is what I expected - which is something that many might still find surprising. The logic (in my mind) for the first operation is:
-2147483648
gets tokenized as '-
' and 2147483648
2147483648
is an unsigned int (since it can't fit into an int - I believe this is different in C99)
- applying the unary '
-
' operator results in 2147483648
again due to unsigned arithmetic rules
- converting that into a long long doesn't change the sign.
The logic for the second operation is:
-2147483647
gets tokenized as '-
' and 2147483647
2147483647
is a signed int
- subtracting
1
results in -2147483648
since there's no problem representing that number
- converting that into a long long doesn't change the sign.