In C, following C99 rules since long long
did not come out until then:
2147483648
is not a 32-bit int
. It is a 64-bit integer as 2147483648
is not in the int32_t
positive range.
-2147483648
is not a 32-bit int
. It is a 64-bit integer as 2147483648
is not in the int32_t
positive range either, the -
is applied after the constant type is formed.
The expected math output is the sum with 64-bit math.
int main(void) {
long long a = 2147483648 + 2147483648;
printf("%lld\n", a);
a = 2147483648 + 2147483648 + 2147483648;
printf("%lld\n", a);
return 0;
}
Output
4294967296
6442450944
OP reports:
Well, the output for me is 0 and 2147483648 when I copied your code.
OP is perhaps using a C89 compiler with long long
extensions. visual-studio-2019 is not fully C99 compliant. Example Does Visual Studio 2017 fully support C99?.
In that case:
C89 uses different rules e.g.:
2147483648
is not a 32-bit int
. It is a 32-bit unsigned long
2147483648 + 2147483648
is unsigned overflow and well defined to sum to 0.
2147483648 + 2147483648 + 2147483648
, as 32-bit unsigned long
math is a 32-bit unsigned long 2147483648
.
Assigning 32-bit unsigned long 2147483648
to a long long
is the same value, different type.
Moral of the story: Consider starting computation with the desired end type.
With the below code, the type on the left does not influence the addition on the right. This is the same problem as Why (not) write 1,000,000,000 as 1000*1000*1000?
long long a = 2147483648 + 2147483648 + 2147483648;
Alternatives:
long long a = (long long) 2147483648 + 2147483648 + 2147483648;
long long a = 0LL + 2147483648 + 2147483648 + 2147483648;
long long a = 2147483648;
a += 2147483648;
a += 2147483648;