0

I'm using MSVC 2019, and I'm testing something.

Thanks to lots of people, now I get this prints 0 :

long long a = 2147483648 + 2147483648;
printf("%lld\n", a);

So this time, I thought like 'what if I add 2147483648 for 3 times?', and I did.

I thought that the result must be -2147483648, because 2147483648 + 2147483648 + 2147483648 is equal to 0 + 2147483648, and 0 and 2147483648 is int value, so it's gonna be -2147483648

In simple terms, I thought that the previous code is equal to this:

long long a = (int)2147483648;
printf("%lld\n", a);

But it didn't work. Here's the code what I wrote:

long long a = 2147483648 + 2147483648 + 2147483648;
printf("%lld\n", a);

The result is 2147483648, and I don't know why.

Now I'm getting dizzy LOL

What did I do wrong?

p.s. the file's name is tmp.c

Hoseong Jeon
  • 1,150
  • 8
  • 20
  • 1
    @user4581301 But when I add 4 times, like `2147483648 + 2147483648 + 2147483648 + 2147483648`, than it give me `0`, which is correct answer I think. – Hoseong Jeon May 06 '20 at 01:48
  • 1
    This depends on architecture. A `long long int` can be the same as an `int64_t` which can hold a max value of `9223372036854775807` just fine.. so adding `3 * max_int` will fit perfectly fine (`6442450944`).. https://ideone.com/VQq50M – Brandon May 06 '20 at 01:51
  • @user4581301 no.. he's adding 64-bit integers.. `2147483645` is 32-bit and he is adding `2147483648`. If he did `long long int some_var = 3 * std::numeric_limits::max()` then he's have int32 overflow. I changed my statement to say `can` instead of `is` for `A long long int is the same..` Sorry about that confusion. – Brandon May 06 '20 at 01:58
  • VS-2019 shows for me (`2147483648` - undefined value and it's random what it shows): https://rextester.com/AMJ46137 but clang and gcc and icc all show `6442450944` (tested with https://godbolt.org/z/M7Zeu5).. I'd guess it's a msvc compiler bug but I don't know for sure. – Brandon May 06 '20 at 02:16
  • @Brandon, we're both guilty of poorly worded comments. Hoseong Jeon's [previous question](https://stackoverflow.com/questions/61624859/why-does-long-long-2147483627-1-2147483628) played with overflows and their expected result here followed the logic of the previous question's 32-bit math. As far as I can tell your interpretation and expected results are correct, so something funny is going on. I'm going to pull out of this one and wait for clarification. – user4581301 May 06 '20 at 02:17
  • Note: There is no signed integer overflow here. – chux - Reinstate Monica May 06 '20 at 02:18

1 Answers1

4

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;
chux - Reinstate Monica
  • 113,725
  • 11
  • 107
  • 213
  • Well, the output for me is `0` and `2147483648` when I copied your code. – Hoseong Jeon May 06 '20 at 02:01
  • OP is asking about MSVC, not standard C. See their previous question. However, they have not supplied code for this question and it is unclear as stated, so it should be closed until they fix this. – Eric Postpischil May 06 '20 at 02:04
  • Okay, I'll edit my question. Can you tell me what I should add? – Hoseong Jeon May 06 '20 at 02:13
  • 1
    @HoseongJeon I think folks are looking for the original code appended to the question, you used to determine the sum. Something like this answer, but what you coded - a minor coding difference to you may be important for others. – chux - Reinstate Monica May 06 '20 at 02:15
  • @chux-ReinstateMonica Ahh got it. I'll edit my question right now. – Hoseong Jeon May 06 '20 at 02:18
  • @HoseongJeon also include the name of the file. I'm not familiar enough with Visual Studio to know if it does this or not, but some IDEs decide which compiler or rules to use, C or C++, based on the file extension. – user4581301 May 06 '20 at 02:24
  • @HoseongJeon the best thing to do is make a small program that does nothing but expose the behaviour you are asking about. It doesn't seem to matter much here, but in many cases the real mistake turns out to be in a bit of the program the asker left out. What you want to give is a complete program anyone can compile, though in this case it looks like they'll also need a copy of visual studio 2019. – user4581301 May 06 '20 at 02:30