【问题标题】:Understanding 2^31 and -2^31 integer promotion了解 2^31 和 -2^31 整数提升
【发布时间】:2016-05-09 22:12:27
【问题描述】:
#include <stdio.h>

int main() {
    printf("sizeof(int): %zu\n", sizeof(int));
    printf("%d\n", 2147483648u > -2147483648);
    printf("%d\n", ((unsigned int)2147483648u) > ((int)-2147483648));
    printf("%d\n", 2147483648u != -2147483648);
    printf("%d\n", ((unsigned int)2147483648u) != ((int)-2147483648));
    return 0;
}

此代码在 C 和 C++ 中的输出,在 cygwin64 和具有 gcc 5.2.0 的 rhel6.4 机器上是:

sizeof(int): 4
1
0
1
0

根据“Integer promotions”,2147483648u 将是 unsigned int 类型(即使没有 u 后缀)和 -2147483648 类型为 int(和往常一样)。为什么显式转换的结果不同?

根据“Usual arithmetic conversions”,本段适用:

否则,符号不同:如果操作数带有 无符号类型的转换等级大于或等于 有符号操作数的类型,然后是有符号类型的操作数 被隐式转换为无符号类型

这意味着正确的结果是这样的:

2147483648u > 2147483648u
2147483648u != 2147483648u

被执行,因为在 32 位中,有符号的 -2^31 和无符号的 2^31 具有相同的表示。换句话说,强制转换的结果是正确的。怎么回事?

我觉得不知何故,在没有强制转换的情况下应用了更高等级的整数提升,所以我得到了例如双方都进行了 64 位签名促销 - 但为什么呢?

两个可执行文件都是64位编译的,这个能起作用吗?

【问题讨论】:

  • @FUZxxl:在这种情况下不是。
  • @FUZxxl:我认为 SO 上的“它们不同”在某些地方有点过分了。比如这个。
  • @FUZxxl:我已经多次确定两种语言的行为是相同的(以及当今常用的各个标准之间)。它属于这两个类别。
  • @Irfy 不,它没有。请选择一个。如果我说“我确保 1+1 在语言 x、y 和 z 中做同样的事情,所以我关于 1+1 的问题属于他们所有人”那同样是错误的。
  • @FUZxxl:如果您不想进行讨论也没关系,但请划清界限,告诉人们某事已在元数据上“决定” 't,至少不是the last time I looked

标签: c++ c implicit-conversion integer-promotion


【解决方案1】:

没有负整数常量。只有应用了一元 - 运算符的正数。

由于2147483648 &gt; INT_MAX,将2147483648 提升为下一个更大的有符号(因为您没有附加u)整数类型,之前应用-


顺便说一句,这就是为什么INT_MIN 通常在&lt;limits.h&gt; 中定义为(-INT_MAX - 1)。 ;-)

【讨论】:

  • 哇,这在我用 c/c++ 编码的 17 年里从来没有打动过我 :-)
  • my 的情况下,我很幸运,事实就是如此。但是win64的long是4个字节,所以如果我用VC编译器完成,就不会这样了。
  • 如果您想达到限制,请尝试输入 -2^63 和 -2^127(计算)作为文字 :)
  • @lrfy:使用(-LLONG_MAX - 1),前者(比较)容易。据我所知,后者在不使用较小宽度常量的乘法或位移的情况下是行不通的。 GCC 支持__int128_t,但不支持整数常量宽度。
猜你喜欢
  • 2020-12-09
  • 1970-01-01
  • 2023-03-21
  • 2013-11-24
  • 1970-01-01
  • 2022-07-12
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
相关资源
最近更新 更多