根据 this interesting paper about undefined behavior optimization in c , 表达式 (x<<n)|(x>>32-n)
“当 n = 0 时在 C 中执行未定义的行为”。 This stackoverflow discussion确认负整数的行为是未定义的,并讨论了左移值的其他一些潜在陷阱。
考虑以下代码:
#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;
}
使用以下参数编译:-O3 -std=c11 -pedantic -Wall -Wextra
- 在 gcc >5.1.0 中程序的输出是
10
. - 在 clang >3.7.0 中输出为
4294967295
.
有趣的是,用 C++ 编译时仍然如此:gcc results , clang results .
因此,我的问题如下:
- 根据我对标准语言的理解,这应该不调用未定义/实现定义的行为,因为两个参数都是无符号整数并且没有一个值是负数。这样对吗?如果不是,c11 和 c++11 标准的相关部分是什么?
- 如果前面的陈述是正确的,那么哪个编译器会根据 c/c++ 标准生成正确的输出?直觉上,左移没有数字应该返回值,即 gcc 输出的值。
- 如果不是上述情况,为什么没有关于此代码可能由于左移溢出而调用未定义行为的警告?
最佳答案
来自 [expr.shift],强调我的:
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.
你正在做:
(x >> (32 - n))
使用 n == 0
,所以您将 32 位数字右移 32。因此,UB。
关于c++ - gcc 和 clang 在使用无符号值左移时产生不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35805837/