为什么这个代码不写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;
}
当您通过更多的比特比字长移值,它通常被偏移了mod word-size
。 基本上,通过64个装置移它由0比特等于没有移位在所有移位。 你不应该依赖于这虽然因为它不是由标准定义,它可以在不同的体系结构不同。
移位数位的数目等于或大于其宽度是未定义的行为。 您只能安全地转移0和63位置之间的64位整数。
这从编译器警告应该是一个暗示:
“警告:右移位计数型的> =宽度”
这将导致未定义的行为:
http://sourcefrog.net/weblog/software/languages/C/bitshift.html
好了,你正在改变一个太多次。 你从0到64包容这是一个总的65倍移。 你一般都希望:
for(int i=0; i < 64; i++)
....
我得到:
test.c:8: warning: right shift count >= width of type
所以也许这是未定义的行为?
您溢出的转变。 如果您发现,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;
}
会产生你所期望的输出。
-1位模式看起来像0xFFFFFFFFFFFFFFFF十六进制,64位的类型。 因此,如果你打印为无符号变量,你会看到一个无符号64位变量可以容纳最大的值,即18446744073709551615。
当比特移位我们不关心什么是值在这种情况下意味着,即如果变量带有符号是同样的方式对待(所有位移一步向右在这种情况下)也没关系。
粗心的另一个陷阱:我知道这是一个古老的线程,但我来到这里寻求帮助。 我得到了使用1周<< k当我的意思是1L << k中的64位计算机上抓出来; 没有在这种情况下,编译器帮助:(
您可以使用:
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
否则。