c++ - gcc 和 clang 在使用无符号值左移时产生不同的输出

标签 c++ c language-lawyer undefined-behavior

根据 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 .

因此,我的问题如下:

  1. 根据我对标准语言的理解,这应该调用未定义/实现定义的行为,因为两个参数都是无符号整数并且没有一个值是负数。这样对吗?如果不是,c11 和 c++11 标准的相关部分是什么?
  2. 如果前面的陈述是正确的,那么哪个编译器会根据 c/c++ 标准生成正确的输出?直觉上,左移没有数字应该返回值,即 gcc 输出的值。
  3. 如果不是上述情况,为什么没有关于此代码可能由于左移溢出而调用未定义行为的警告?

最佳答案

来自 [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/

相关文章:

c++ - "this"指针变为空 c++

c++ - 本地类变量位置

c++ - C++-运算符= self 分配检查

c - 从管道读取时循环未完成

c++ - 'auto t = new decltype(nullptr)' 是做什么的?

java - 带分组的拓扑排序

c - 交换未知变量类型的每两位

c - C中的可变大小数组

c++ - 将非类非数组纯右值转换为 cv 限定类型是否合法?

c++ - 奇怪地相互重复的类定义