0

I've been looking at this piece of code for an hour now... I desperately try to find the error.

#include <iostream>

int main()
{
    for (int32_t n = 1; n>= 0; n--)
    {
        std::cout << "n: " << n << std::endl;
        std::cout << std::dec << "  64 - n: " << (64 - n) << std::endl;
        std::cout << std::hex << "  0x1ULL << 64: " << (0x1ULL << 64) << std::endl;
        std::cout << std::hex << "  0x1ULL << (64 - n): " << (0x1ULL << (64 - n)) << std::endl;
    }
}

And that's the output:

n: 1
  64 - n: 63
  0x1ULL << 64: 0
  0x1ULL << (64 - n): 8000000000000000
n: 0
  64 - n: 64
  0x1ULL << 64: 0
  0x1ULL << (64 - n): 1

Why is (0x1ULL << 64) different from (0x1ULL << (64 - n)) for n = 0? The type of n does not seem to matter.

It's the same with each version of GCC. Feel free to try out online: http://www.compileonline.com/compile_cpp11_online.php

2 Answers2

8

You have undefined behaviour:

C++11 5.8/1 The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

So, assuming long long has 64 bits, shifting by 64 bits will give undefined behavoiur.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • +1 Related, in-depth explanation [here](http://stackoverflow.com/a/22734721/183120). – legends2k Apr 07 '14 at 10:36
  • Wow, what a daft rule. Whoever created that rule has no clue about processors. The underlying assembler instructions handle those cases correctly. In result, GCCs adds effort to produce undefined behaviour - that's quite an achievement. Anyway, thank you! – user3497687 Apr 07 '14 at 10:54
  • 5
    @user3497687: Actually, that rule is because whoever created it *does* know that different processors behave in different ways when a shift overflows; so specifying the behaviour would add effort on processors that naturally behave differently. GCC doesn't "add effort" - it just uses the native shift operation, and gives whatever result that produces. – Mike Seymour Apr 07 '14 at 10:55
0

left shift count should be less that width of type. In this case, width of type int32_t is 32 bits and you are shifting more than its capacity. That's wrong.

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69