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 ),这样可以保证工作。