64位移位问题

时间:2009-06-21 23:06:07

标签: c++ 64-bit

为什么这段代码不会写0作为最后一个元素但是18446744073709551615? (用g ++编译)

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

9 个答案:

答案 0 :(得分:13)

当您将值移位多于字大小时,通常会移动mod word-size。基本上,将其移位64意味着移位0位,这相当于根本没有移位。您不应该依赖于此,因为它没有被标准定义,并且在不同的体系结构上可能会有所不同。

答案 1 :(得分:7)

将数字移动等于或大于其宽度的位数是未定义的行为。您只能安全地移动0到63位之间的64位整数。

答案 2 :(得分:3)

编译器的这个警告应该是一个提示:

“警告:右移计数&gt; =类型宽度”

这会导致未定义的行为:

http://sourcefrog.net/weblog/software/languages/C/bitshift.html

答案 3 :(得分:1)

好吧,你换了太多次了。你从0到64(包括0和64),总共65次。你通常想要:

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

答案 4 :(得分:1)

我明白了:

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

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

答案 5 :(得分:1)

你溢出了班次。如果您注意到,GCC甚至会警告您:

warning: right shift count >= width of type

为什么?您将64包含为有效的shift,这是一种未定义的行为。 从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;
}

会产生你期望的输出。

答案 6 :(得分:0)

对于64位类型,-1的位模式在十六进制中看起来像0xFFFFFFFFFFFFFFFF。因此,如果将其打印为无符号变量,您将看到无符号64位变量可以容纳的最大值,即18446744073709551615.

当位移时,我们不关心在这种情况下值是什么意思,即如果变量是有符号或无符号无关紧要,则以相同的方式对待它(在这种情况下将所有位向右移一步) )。

答案 7 :(得分:0)

粗心的另一个陷阱:我知道这是一个老线程,但我来到这里寻求帮助。当我的意思是1L&lt;&lt; k;而我使用1&lt;&lt; k时,我被困在64位机器上在这种情况下,编译器没有帮助:(

答案 8 :(得分:0)

您可以使用:

static inline pack_t lshift_fix64(pack_t shiftee, short_idx_t shifter){ return (shiftee << shifter) & (-(shifter < 64)); } 对于这样一个技巧,(-(shifter < 64)) == 0xffff ffff ffff ffff if shifter&lt; 64和(-(shifter < 64)) == 0x0否则。