64位转移问题(64bit shift problem)

2019-06-23 19:50发布

为什么这个代码不写0作为最后一个元素,但18446744073709551615? (编译克++)

#include <iostream>

using namespace std;
int main(){
    unsigned long long x = (unsigned long long) (-1);
    for(int i=0; i <= 64; i++)
        cout << i << " " << (x >> i) << endl;
    cout << (x >> 64) << endl;
    return 0;
}

Answer 1:

当您通过更多的比特比字长移值,它通常被偏移了mod word-size 。 基本上,通过64个装置移它由0比特等于没有移位在所有移位。 你不应该依赖于这虽然因为它不是由标准定义,它可以在不同的体系结构不同。



Answer 2:

移位数位的数目等于或大于其宽度是未定义的行为。 您只能安全地转移0和63位置之间的64位整数。



Answer 3:

这从编译器警告应该是一个暗示:

“警告:右移位计数型的> =宽度”

这将导致未定义的行为:

http://sourcefrog.n​​et/weblog/software/languages/C/bitshift.html



Answer 4:

好了,你正在改变一个太多次。 你从0到64包容这是一个总的65倍移。 你一般都希望:

for(int i=0; i < 64; i++)
    ....


Answer 5:

我得到:

test.c:8: warning: right shift count >= width of type

所以也许这是未定义的行为?



Answer 6:

您溢出的转变。 如果您发现,GCC甚至警告你:

warning: right shift count >= width of type

怎么会? 你包括64作为一个有效的转变,这是一个未定义的行为。 从0到64计数有65个数字(0在内)。 0是第一个位(很像阵列)。

#include <iostream>

using namespace std;
int main(){
    unsigned long long x = (unsigned long long) (-1);
    for(int i=0; i < 64; i++)
        cout << i << " " << (x >> i) << endl;
    cout << (x >> 63) << endl;
    return 0;
}

会产生你所期望的输出。



Answer 7:

-1位模式看起来像0xFFFFFFFFFFFFFFFF十六进制,64位的类型。 因此,如果你打印为无符号变量,你会看到一个无符号64位变量可以容纳最大的值,即18446744073709551615。

当比特移位我们不关心什么是值在这种情况下意味着,即如果变量带有符号是同样的方式对待(所有位移一步向右在这种情况下)也没关系。



Answer 8:

粗心的另一个陷阱:我知道这是一个古老的线程,但我来到这里寻求帮助。 我得到了使用1周<< k当我的意思是1L << k中的64位计算机上抓出来; 没有在这种情况下,编译器帮助:(



Answer 9:

您可以使用:

static inline pack_t lshift_fix64(pack_t shiftee, short_idx_t shifter){ return (shiftee << shifter) & (-(shifter < 64)); } static inline pack_t lshift_fix64(pack_t shiftee, short_idx_t shifter){ return (shiftee << shifter) & (-(shifter < 64)); }这样的特技, (-(shifter < 64)) == 0xffff ffff ffff ffff如果移位器<64和(-(shifter < 64)) == 0x0否则。



文章来源: 64bit shift problem
标签: c++ 64bit