简体   繁体   English

unsigned long int是否适合此操作?

[英]Is unsigned long int correct for this operation?

Here's my code: 这是我的代码:

#include <stdio.h>

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);
}

It's returning that x = 18446744071562067968. I read that unsigned long int should go up to 4,294,967,296, so why can't I use 1 << 32 to set x equal to 2,147,483,648? 返回x =18446744071562067968。我读到unsigned long int应该达到4,294,967,296,所以为什么不能使用1 << 32将x设置为2,147,483,648?

1 << 31 causes undefined behaviour, if your system has 32-bit ints. 如果您的系统具有32位整数,则1 << 31会导致未定义的行为。 The literal 1 is a signed int. 文字1是带符号的int。

You need to do an unsigned shift instead of a signed shift: 您需要执行无符号移位而不是有符号移位:

x = 1UL << 31;

I added L so that the code is still correct even on a 16-bit system, and it doesn't hurt to do so. 我加了L这样即使在16位系统上,代码仍然是正确的,这样做也没有什么害处。


Informally, shifting a 1 into the sign bit is undefined. 非正式地,将1移到符号位是不确定的。 The formal text can be found in section 6.5.7/4 of the C11 standard: 正式文本可以在C11标准的6.5.7 / 4部分中找到:

The result of E1 << E2 is E1 left-shifted E2 bit positions; E1 << E2的结果是E1左移E2位位置; vacated bits are filled with zeros. 空位用零填充。 [...] If E1 has a signed type and nonnegative value, and E1 × 2 E2 is representable in the result type, then that is the resulting value; [...]如果E1具有带符号的类型和非负值,并且E1 × 2 E2在结果类型中可表示,则这就是结果值; otherwise, the behavior is undefined. 否则,行为是不确定的。


Your other question, "why can't I use 1 << 32 " is covered by that same quote. 您的另一个问题“为什么我不能使用1 << 32 ”被相同的引号覆盖。 What about 1UL << 32 ? 1UL << 32呢? If your system has 32-bit unsigned long then this would also be undefined according to 6.5.7/3: 如果您的系统具有32位unsigned long那么根据6.5.7 / 3,这也将是未定义的:

[...] If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined [...]如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为不确定

But it would work if your system had 64-bit unsigned long . 但是,如果您的系统具有64位unsigned long它将可以工作。 To avoid having your code break when compiled on a different system (this goal is known as code portability ) you could write (uint64_t)1 << 32 (or 1ULL << 32 ) which is guaranteed to work. 为了避免在其他系统上编译时出现代码中断(此目标称为代码可移植性 ),您可以编写(uint64_t)1 << 32 (或1ULL << 32 )以保证工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM