0

A silly question. I just made a few tests. My expectation was that after:

uint32_t v = ~ (uint32_t) 0;
v <<= sizeof(uint32_t) * 8;

or

size_t v = ~ (size_t) 0;
v <<= sizeof(size_t) * 8;

v shall be zero. But it's not - it's equal to original value. So for 64-bit every shift up to 63 does shift bits, but shift by 64 does nothing (equal to shift by 0).
This is controversial for me.

Is this compiler specific or by C++ standard? I'm trying gcc version 8.3.0 under linux. Params are: g++ -c -pipe -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC

ruohola
  • 21,987
  • 6
  • 62
  • 97
truf
  • 2,843
  • 26
  • 39
  • 7
    It's undefined behaviour to shift by the width of the type (or more) – M.M Jul 30 '19 at 20:40
  • 2
    Turn on optimization to re-roll the dice on the outcome – harold Jul 30 '19 at 20:40
  • Your compiler should have given you warnings: https://godbolt.org/z/xnmi7p – CuriouslyRecurringThoughts Jul 30 '19 at 20:44
  • You should have gotten a warning for this, from gcc 8.3 with -Wall – M.M Jul 30 '19 at 20:44
  • 1
    Nothing controversial here, most processors 5/6 bits of the shift when shifting 32/64 bit values. ARM is an exception - it uses 8 bits (when argument is in register). This is probably why Java and C# explicitly specify the same behavior. –  Jul 30 '19 at 20:47
  • I think this falls under "Youse breaka da rules, compiler breaka da program." – Eljay Jul 30 '19 at 21:22

1 Answers1

1

You are knee-deep in undefined behavior:

In any case, if the value of the right operand is negative or is greater or equal to the number of bits in the promoted left operand, the behavior is undefined.

https://en.cppreference.com/w/cpp/language/operator_arithmetic

SergeyA
  • 61,605
  • 5
  • 78
  • 137