According to this interesting paper about undefined behavior optimization in c, the expression (x<<n)|(x>>32-n)
"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
10
. - In clang >3.7.0 the output is
4294967295
.
Interestingly, this is still true when compiling with c++: gcc results, clang results.
Therefore, my questions are as follows:
- 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?
- 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.
- If the above is not the case, why are there no warnings that this code may invoke undefined behavior due to left-shift overflow?