1

The code below, when compiled, throws a warning caused by line 9:

warning: shift count >= width of type [-Wshift-count-overflow]

However, line 8 does not throw a similar warning, even though k == 32 (I believe). I'm curious why this behavior is occurring? I am using the gcc compiler system.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int bit_shift(unsigned x, int i){
    int k = i * 8;
    unsigned n = x << k; /* line 8 */
    unsigned m = x << 32; /* line 9 */
    return 0;
} 

int main(){
    bit_shift(0x12345678, 4);
    return 0;
}
Daniel
  • 2,345
  • 4
  • 19
  • 36
  • The compiler won't know that `k >= 32` by seeing only the function `bit_shift`. Checking invocation of that may be too much work for the compilers. – MikeCAT Oct 02 '20 at 17:49
  • 1
    `x << 32` is UB, the range of a shift count is 0-31 only (at least on platforms where `unsigned` is 32 bits) – David Ranieri Oct 02 '20 at 17:50

2 Answers2

3

The value of k in bit_shift is dependent on the parameter i. And because bit_shift is not declared static it is possible that it could be called from other translation units (read: other source files).

So it can't determine at compile time that this shift will always be a problem. That is in contrast to the line unsigned m = x << 32; which always shifts by an invalid amount.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thanks for this quick and great explanation! +1 – Daniel Oct 02 '20 at 17:53
  • 2
    Re “So it can't determine at compile time that this shift will always be a problem” Not knowing that something will always be a problem is not grounds for not warning. If you know there **will** be a problem on at least one occasion, you should warn. The actual issue here would be that the compiler does not recognize the problem at all; it does not see there is a problem in any circumstance. – Eric Postpischil Oct 02 '20 at 18:05
  • @EricPostpischil: Though interestingly, if you write `k = 32; n = x << k;`, gcc clearly "knows" that `k` is `32` and it propagates the constant accordingly, but it still doesn't give a warning. https://godbolt.org/z/5K8aro Arguably a gcc bug? – Nate Eldredge Oct 02 '20 at 19:13
  • @NateEldredge I am using `gcc`, to confirm (question edited to note this) – Daniel Oct 02 '20 at 19:43
  • @NateEldredge that is a good observation which cuts to the core of what I am wondering about here. – Daniel Oct 02 '20 at 19:45
1

I think why Line 8 does not throw a warning is because left shifting an unsigned int32 >= 32 bits is NOT an undefined behavior.

C standard (N2716, 6.5.7 Bitwise shift operators) says:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined

KagurazakaKotori
  • 562
  • 4
  • 14