ruser45381 ruser45381 - 17 days ago 4
C Question

gcc and clang produce different outputs while left-shifting with unsigned values

According to this interesting paper about undefined behavior optimization in c, the expression

"performs undefined behavior in C when n = 0". This stackoverflow discussion confirms that the behavior is undefined for negative integers, and discusses some other potential pitfalls with left-shifting values.

Consider the following code:

#include <stdio.h>
#include <stdint.h>

uint32_t rotl(uint32_t x, uint32_t n)
return (x << n) | (x >> (32 - n));

int main()
uint32_t y = rotl(10, 0);
printf("%u\n", y);
return 0;

Compile using the following parameters:
-O3 -std=c11 -pedantic -Wall -Wextra

  • In gcc >5.1.0 the output of the program is

  • In clang >3.7.0 the output is

Interestingly, this is still true when compiling with c++: gcc results, clang results.

Therefore, my questions are as follows:

  1. It is my understanding from the language in the standard that this should not invoke undefined / implementation defined behavior since both of the parameters are unsigned integers and none of the values are negative. Is this correct? If not, what is the relevant section of the standard for c11 and c++11?

  2. If the previous statement is true, which compiler is producing the correct output according to the c/c++ standard? Intuitively, left shifting by no digits should give you back the value, i.e. what gcc outputs.

  3. If the above is not the case, why are there no warnings that this code may invoke undefined behavior due to left-shift overflow?


From [expr.shift], emphasis mine:

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.

You are doing:

(x >> (32 - n))

with n == 0, so you're right-shifting a 32-bit number by 32. Hence, UB.