Left shift can be set to ZERO

I have a doubt in the left hand shift operator

int i = 1; i <<= (sizeof (int) *8); cout << i; 

He is typing 1.

  • I was initialized 1.
  • And by moving the bits to the size of an integer, it fills LSB 0, and when 1 crosses the integer limit, I expected the output to be 0.

How and why is it 1?

+4
source share
4 answers

Say sizeof(int) is 4 on your platform. Then the expression will take the form:

 i = i << 32; 

The standard says:

6.5.7-3

If the value of the right operand is negative or greater than or equal to the width of the advanced left operand , undeformed behavior is defined.

+14
source

As cnicutar said , your example demonstrates undefined behavior. This means that the compiler can do everything that suits the vendor, including forcing demons to fly out of your nose or just do nothing for the value at hand.

What can you do to convince yourself that shifting by the number of bits will result in an expression of 0 :

 int i = 1; i <<= (sizeof (int) *4); i <<= (sizeof (int) *4); cout << i; 
+3
source

Extension on previous answer ...

On the x86 platform, your code will be compiled something like this:

 ; 32-bit ints: mov cl, 32 shl dword ptr i, cl 

The CPU will shift dword in variable i by the value contained in the cl register modulo 32. Thus, 32 modulo 32 gives 0. Therefore, the shift does not actually occur. And this works great for standard C. In fact, what the standard C says in 6.5.7-3 is that the above processor behavior was pretty common on the same day and affected the standard.

+2
source

As others have mentioned, according to the C standard, the shift behavior is undefined.

Thus, the program prints 1. The low-level explanation of why it prints 1 is as follows:

When compiling without optimization, the compiler (GCC, clang) generates the SHL command:

 ... mov $32,%ecx shll %cl,0x1c(%esp) ... 

Intel's documentation for the SHL instruction states:

SAL / SAR / SHL / SHR-Shift

The score is masked up to 5 bits (or 6 bits if used in 64-bit mode and REX.W is used). The sampling range is limited to 0 - 31 (or 63 if 64-bit mode and REX.W are used).

Masking the shift counter 32 (binary 00100000) to 5 bits gives 0 (binary 00000000). Therefore, the shll %cl,0x1c(%esp) does not perform any shifts and leaves the value of i unchanged.

+1
source

Source: https://habr.com/ru/post/1398203/


All Articles