为什么这段代码不会写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;
}
答案 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)
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
否则。