【问题标题】:Bit Shifting: Shift Count >= Width Of Type移位:移位计数 >= 类型宽度
【发布时间】:2020-10-02 17:47:56
【问题描述】:

下面的代码在编译时会抛出由第 9 行引起的警告:

警告:移位计数 >= 类型 [-Wshift-count-overflow] 的宽度

但是,第 8 行并没有发出类似的警告,即使 k == 32(我相信)。我很好奇为什么会发生这种行为?我正在使用gcc 编译器系统。

#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;
}

【问题讨论】:

  • 编译器不会通过只看到函数bit_shift 知道k &gt;= 32。检查它的调用对于编译器来说可能是太多的工作。
  • x &lt;&lt; 32 是 UB,移位计数的范围仅为 0-31(至少在 unsigned 为 32 位的平台上)

标签: c compilation bit compiler-warnings bit-shift


【解决方案1】:

bit_shiftk 的值取决于参数i。而且因为bit_shift 没有声明为static,所以它可能会被其他翻译单元调用(阅读:其他源文件)。

因此它无法在编译时确定这种转变是否总是一个问题。这与unsigned m = x &lt;&lt; 32; 行相反,它总是移动一个无效的量。

【讨论】:

  • 感谢您提供快速而精彩的解释! +1
  • Re “所以它不能在编译时确定这种转变是否总是一个问题” 不知道某事总是有问题不是不警告的理由。如果您知道至少有一次出现问题,则应发出警告。这里的实际问题是编译器根本无法识别问题。它在任何情况下都没有发现问题。
  • @EricPostpischil:虽然有趣的是,如果你写k = 32; n = x &lt;&lt; k;,gcc 清楚地“知道”k32,它会相应地传播常量,但它仍然没有给出警告. godbolt.org/z/5K8aro 可以说是 gcc 错误?
  • @NateEldredge 我正在使用gcc 进行确认(已编辑问题以说明这一点)
  • @NateEldredge 这是一个很好的观察,它切入了我在这里想知道的核心。
【解决方案2】:

我认为第 8 行没有发出警告的原因是因为左移 unsigned int32 >= 32 位 不是未定义的行为

C 标准(N2716,6.5.7 位移位运算符)说:

E1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多