为什么通过全宽移位表现不同的常数与变数?

问题描述 投票:3回答:2

如果我使用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);
}
c bit-shift
2个回答
5
投票

在所有现代PC类平台,int只有32位。超过该转移是不确定的。并记住,比特数为是基于零的,因此对于一个32位的类型(如int),那么有效位的范围是031(含)移位。

现在对于3 << 323 << sz之间的差:在第一情况下,编译器可以知道它移超过32位,因此它可以推断出,这将是一个64位操作(使用long long)。在第二种情况下,编译器不知道sz的价值,因为它是一个简单的变量,而不是一个编译时间常数。因此,它必须假定,这是一个简单的移位intsz的值的范围。


5
投票

C标准仅定义为偏移小于类型的宽度被移位(C 2018 6.5.7 3)移行为。由32位移位32位int不是由标准限定。

由于编译器评价在编译时前者3 << 32(0x3) << sz可能出现之间的差异(可能使用了这一点改变所有的位,导致零的操作)和在执行时后者(可能使用仅使用低5位的指令的移位量的,导致没有偏移)。这种行为可能不能依靠;他们可能与优化,目标或其他编译器配置的变化,编译器版本的变化而变化,等等。

© www.soinside.com 2019 - 2024. All rights reserved.