unsigned long int对此操作是否正确?
这是我的代码:
#include int main(int argc, char *argv[]) { unsigned long int x = 0; // trying to make x = 2,147,483,648 x = 1 << 31; printf("%lu", x); }
它返回x = 18446744071562067968。我读到unsigned long int应该达到4,294,967,296,那么为什么我不能用1 << 32来设置x等于2,147,483,648?
如果您的系统具有32位整数,则1 << 31
会导致未定义的行为。 文字1
是带符号的int。
您需要执行无符号移位而不是签名移位:
x = 1UL << 31;
我添加了L
,即使在16位系统上代码仍然正确,这样做并没有什么坏处。
非正式地,将1
移入符号位是不确定的。 正式文本见C11标准第6.5.7 / 4节:
E1 << E2
的结果是E1
左移E2
位位置; 腾出的位用零填充。 [...]如果E1
具有有符号类型和非负值,并且E1
×2
E2
可在结果类型中表示,那么这就是结果值; 否则,行为未定义。
你的另一个问题,“为什么我不能使用1 << 32
”被同一个引用所涵盖。 1UL << 32
怎么样? 如果你的系统有32位unsigned long
那么根据6.5.7 / 3,这也是未定义的:
[...]如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义
但是如果你的系统有64位unsigned long
。 为了避免在不同系统上编译时代码中断(这个目标称为代码可移植性 ),您可以编写(uint64_t)1 << 32
(或1ULL << 32
),这样可以保证工作。