为什么恒定宽度和可变宽度按全角宽度移动会有不同的表现?

时间:2019-02-08 09:21:52

标签: c bit-shift

如果我使用3 << 32,则会得到正确的结果。 如果我使用sizeof(int)找到大小,然后乘以8,将结果存储在变量中,然后使用3 << variable,则会得到不同的结果。我在这里想念什么?

void func()
{
    unsigned int sz = sizeof(number) * 8;
    unsigned int k = 0;
    printf("Value of sz is %u \r\n",sz);
    k = (k | (0x3) << sz);
    printf("Value of 2_1_MSB is %d \r\n",(3 << 32));
     printf("Value of k is %u \r\n",k);
}

2 个答案:

答案 0 :(得分:5)

C标准仅针对仅小于要转换类型的宽度的转换定义转换行为(C 2018 6.5.7 3)。标准未定义将32位int移32位。

3 << 32(0x3) << sz之间可能存在差异,这是由于编译器在编译时评估前者(也许使用了将所有位移出,导致为零的操作)而后者在执行时评估的原因(也许使用一条仅使用移位量的低五位的指令,而不会产生移位)。可能不依赖此类行为;它们可能会随着优化,目标或其他编译器配置的更改,编译器版本的更改等而改变。

答案 1 :(得分:5)

在所有现代PC型平台上,int只有32位。移位超过未定义。并且请记住,用于移位的位数是从零开始的,因此对于32位类型(如int),有效位数范围是031(包括两端)。

现在了解3 << 323 << sz之间的区别:在第一种情况下,编译器可以知道它要移位32位以上,因此可以推断出它将是64位操作(使用long long)。在第二种情况下,编译器不知道sz的值,因为它是一个普通变量,而不是编译时常量。因此,必须假定这是一个简单的int移位,并且sz的值在范围内。