更新了x的来源。这是一项任务,我被要求填写该职能。赋值的要求是我无法更改参数类型或执行任何类型转换。所以我有这个问题。
我想实现位数使用c。这是代码:
int bitCount(int x) {
int mask1 = 0x55555555;
int mask2 = 0x33333333;
int mask3 = 0x0f0f0f0f;
int mask4 = 0x00ff00ff;
int mask5 = 0x0000ffff;
//x = 0xffffffff;
if (x != 0xffffffff) {
exit(0);
}
printf("%x\n", x);
x = (x & mask1) + ((x >> 1) & mask1);
printf("%x\n", x);
x = (x & mask2) + ((x >> 2) & mask2);
printf("%x\n", x);
x = (x & mask3) + ((x >> 4) & mask3);
printf("%x\n", x);
x = (x & mask4) + ((x >> 8) & mask4);
printf("%x\n", x);
x = (x & mask5) + ((x >> 16) & mask5);
printf("%x\n", x);
return x;
}
当x
= -1(或十六进制为0xffffffff
)时,答案应为0x20
。但实际上输出是:
ffffffff
aaaaaaaa
24444444
6080808
e0010
1e
如果我取消注释该行
代码中"x = 0xffffffff"
,输出变为:
ffffffff
aaaaaaaa
44444444
8080808
100010
20
操作系统是Mac OS X. gcc版本是:
gcc --version
配置为:
--prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
为什么?
答案 0 :(得分:7)
首先,负整数的右移是实现定义的:
E1 >> E2
的结果是E1
右移E2
位位置。如果E1
具有无符号类型或E1
具有有符号类型和非负值,则结果的值为积分E1 / 2^E2
的商的一部分。如果E1具有有符号类型和负值,则结果值是实现定义的。
但是,让我们假设我们使用的是x86,并且负整数的右移就像是2的补码表示一样,并产生正确的32位值。如果int x = 0xFFFFFFFF
则x & mask1
为0x55555555
且(x >> 1) & mask
也为0x55555555
,则两者均为正数;他们的总和是0xAAAAAAAA
然后
x = (x & mask1) + ((x >> 1) & mask1);
如果int
为32位宽,会导致有符号整数溢出,因此您的代码具有未定义的行为。 必须使用unsigned int
来代替int
。
我无法在计算机上重现您的错误,但我可以通过在溢出添加后屏蔽x
的符号位来获得相同的输出:
x = (x & mask1) + ((x >> 1) & mask1);
x = x & 0x7FFFFFFF;
只有通过此更改,我才能获得您正在观察的错误输出:
ffffffff
aaaaaaaa
24444444
6080808
e0010
1e
当64位处理器变得越来越普遍时,32位整数的这种未定义行为已经增加了很多 - 根据C标准,允许编译器使用64位寄存器进行32位 signed < / strong>整数,因为它们永远不会溢出,如果你溢出它们,你的&#34; 32位&#34; int
变量甚至可以包含 64位值。
答案 1 :(得分:1)
我准备去睡觉,但后来我对这个答案感到困扰,所以我起床了。我不是关于初始化/不初始化的事情。很难知道,因为你的代码只有1/2,但我认为它更多的是签名/无符号差异。
你正在向右移动,对于带符号的数字保留负位;但对于未签名的不会。看起来您的数字集具有较小的值是在轮班中使用无符号数字的结果。
我注意到您没有指定x
的类型。这对于C
来说真的很奇怪,你真的应该把一个类型放在那个变量的前面。
---原帖如下---
在
中x = 0xffffffff;
您清楚地将变量x
初始化为已知的特定值。
if (x != 0xffffffff) {
根据已知的特定值,清楚地检查未初始化变量x
中的内容。简而言之,在程序运行之前,您根本不知道变量x
的内存是什么,这就是您要阅读的内容。
你只是“幸运”并且有一些“看起来正确”的输出,但是如果你以不同的方式运行它,或者在不同的机器上运行它,你可能根本不会获得相同的输出。