8

I have this code in C (it's for study only):

    char x;
    uint64_t total = 0;

    for(x = 20; x < 30; x++){
        total = (((((1 << x) * x) / 64) + 1) * sizeof(uint64_t));
        printf("%d - %llu\n", x, total);        
    }       

What is printed:

20 - 2621448
21 - 5505032
22 - 11534344
23 - 24117256
24 - 50331656
25 - 104857608
26 - 218103816
27 - 18446744073625665544
28 - 18446744073575333896
29 - 18446744073508225032

Why at x > 26 do I have those strange values? I'm at gcc 4.6.1 on Ubuntu 10.10 64 bits.

Frederico Schardong
  • 1,946
  • 6
  • 38
  • 62
  • looks like the problem is at char x, I used uint64_t for it and works good. – Frederico Schardong Apr 06 '12 at 19:11
  • You will be able to see what is happening more clearly if `total = (((((1 << x) * x) / 64) + 1) * sizeof(uint64_t));` is simplified to `total = ((1 << x) * x);` then printed with `printf("%d - 0x%llx\n", x, total);` you will see the the sign bit turning the nmber negative, which is printed as a huge number by printf("... - %llu\n", ... total); – gbulmer Apr 06 '12 at 19:14
  • duplicates: [GCC left shift overflow](https://stackoverflow.com/q/3871650/995714), [how to use uint64_t in C](https://stackoverflow.com/q/43060408/995714), [What does the C standard say about bitshifting more bits than the width of type?](https://stackoverflow.com/q/11270492/995714), [bit shifting with unsigned long type produces wrong results](https://stackoverflow.com/q/31744305/995714) – phuclv May 30 '22 at 15:13

2 Answers2

23

Because 1 is an int, 32 bits, so (1 << 27)*27 overflows. Use 1ull.

Regarding your comment, if x is a uint64_t, then 1 << x is still an int, but for the multiplication it would be cast to uint64_t, so there'd be no overflow. However, if x >= 31, 1 << x would be undefined behaviour (as the resulting value cannot be represented by a signed 32 bit integer type).

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
0

I guess your problem is, you calculate with 32bit and assign it later to a 64 bit value

division by 64 is the same as not shift 6 bit

char x;
uint64_t one = 1;
uint64_t total = 0;

for(x = 20; x < 30; x++){
    total = ((((one << (x - 6)) * x) + 1) * sizeof(uint64_t));
    printf("%d - %llu\n", x, total);        
}

not compiled yet

stefan bachert
  • 9,413
  • 4
  • 33
  • 40