3

at the beginning, I write a demo to get 2G memory, but the I got a problem like this, I don't know why, what different of num1, num2, num3?

#include<stdio.h>
int main(){
    unsigned long num1 = 1024*1024*1024*2;
    unsigned long num2 = 1024*1024*1024*2.0;
    unsigned long num3 = 1024*1024*1024;
    num3 *= 2;
    printf("num1:%lu\n num2:%lu\n num3:%lu\n", num1, num2, num3);
    return 0;
}

output:

num1:18446744071562067968
num2:2147483648
num3:2147483648
Dorin Botan
  • 1,224
  • 8
  • 19
nick
  • 63
  • 1
  • 6
  • `1024*1024*1024*2` this calculation is performed with `int` data type, since all literals are or type `int`. Consequently, you get _signed integer overflow_, which, I guess is **undefined** (in C++ it's undefined behavior, not sure about C). – Daniel Langr Oct 30 '18 at 07:16
  • 1
    dont you get a warning? – Jean-François Fabre Oct 30 '18 at 07:17
  • very similar to this: https://stackoverflow.com/questions/45281718/overflow-appears-even-when-using-unsigned-long-int – Jean-François Fabre Oct 30 '18 at 07:17
  • 1
    this code gives a warning: `test.c: In function 'main': test.c:3:40: warning: integer overflow in expression [-Woverflow] unsigned long num1 = 1024*1024*1024*2;` always enable warnings. – Jean-François Fabre Oct 30 '18 at 08:13
  • I got this, but I don't know why in that time, but i find the answer now , anyway thanks. – nick Oct 31 '18 at 03:07

1 Answers1

7

The first line, unsigned long num1 = 1024*1024*1024*2;, initializes an unsigned long (num1) with an int. The computation 1024*1024*1024*2 has type int because all the values are int literals. Use the UL suffix on at least one of them to make it unsigned long:

unsigned long num1 = 1024UL*1024*1024*2;

As a precaution, you can prefer putting the suffix on the first value because of the left-to-right associativity of multiplication. That way, all these multiplications are done between values of type unsigned long instead of int.

As for why the other two methods work: the second line initializes num2 with a double, which has enough precision to produce the correct value in this case; the third line initializes num3 with an int as well, but 1024*1024*1024 is representable by a 32-bit int (it's 2^30, which is less than 2^31-1). The multiplication by 2 after that is done on an unsigned long, so it works as expected.

Nelfeal
  • 12,593
  • 1
  • 20
  • 39
  • 1
    The UL is a good idea, yet `1024*1024*1024` is still calculated using `int` math. This overflows 16-bit `int`, common in embedded processors and with other less obvious constants. Best to have the lead constant as `UL` as in `1024UL*1024*1024*2;` so all the computation is done using `unsigned long` math. [See also](https://stackoverflow.com/a/40637622/2410359) – chux - Reinstate Monica Oct 30 '18 at 14:56
  • I know, what a simple solution! thank you.that help me a lot. – nick Oct 31 '18 at 03:06