【问题标题】:Is unsigned long int correct for this operation?unsigned long int 对于此操作是否正确?
【发布时间】:2016-01-31 20:32:56
【问题描述】:

这是我的代码:

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

它返回 x = 18446744071562067968。我读到 unsigned long int 应该达到 4,294,967,296,那么为什么我不能使用 1

【问题讨论】:

标签: c long-integer bit-shift


【解决方案1】:

1 &lt;&lt; 31 会导致未定义的行为,如果您的系统具有 32 位整数。文字 1 是有符号整数。

你需要做一个无符号移位而不是一个有符号移位:

x = 1UL << 31;

我添加了L,这样即使在 16 位系统上代码仍然正确,这样做也没有什么坏处。


非正式地,将1 移入符号位是未定义的。正式文本可以在 C11 标准的第 6.5.7/4 节中找到:

E1 &lt;&lt; E2 的结果是E1 左移E2 位位置;空出的位用零填充。 [...] 如果E1 具有带符号类型和非负值,并且E1 × 2E2 在结果类型中是可表示的,那么这就是结果值;否则,行为未定义。


你的另一个问题,“为什么我不能使用1 &lt;&lt; 32”也包含在同一个引用中。 1UL &lt;&lt; 32 呢?如果您的系统有 32 位 unsigned long,那么根据 6.5.7/3,这也将是未定义的:

[...] 如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义

但如果您的系统有 64 位 unsigned long,它会起作用。为避免在不同系统上编译时代码中断(此目标称为代码可移植性),您可以编写保证工作的(uint64_t)1 &lt;&lt; 32(或1ULL &lt;&lt; 32)。

【讨论】:

    猜你喜欢
    • 2012-10-10
    • 1970-01-01
    • 2016-07-29
    • 2022-12-20
    • 2023-04-07
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 2014-04-03
    相关资源
    最近更新 更多