【发布时间】:2012-08-30 06:29:17
【问题描述】:
情况:
我有一段代码在编译为 32 位时有效,但在使用 gcc 4.6 编译为 64 位时失败。在确定问题并阅读标准后,我无法真正理解为什么它适用于 32 位。我希望有人能解释发生了什么。
代码(稍微简化并减少到有趣的部分):
// tbl: unsigned short *, can be indexed with positive and negative values
// v: unsigned int
// p: unsigned char *
tmp = tbl[(v >> 8) - p[0]]; // Gives segfault when not compiled with -m32
当使用-m32 编译时,代码可以工作。在没有-m32 的情况下编译时会出现段错误。 segfault 的原因是 (v >> 8) - p[0] 在编译为 64 位时被解释为 unsigned int ,而对于“负”结果将很遥远。
根据this 问题,C99 标准说明如下:
6.2.5c9:A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
由此看来,unsigned 减去 unsigned 将始终导致 unsigned 输出,这与 64 位情况下发生的情况一致。这在 32 位的情况下似乎不会发生,这让我觉得非常奇怪。
谁能解释一下在 32 位的情况下发生了什么?
【问题讨论】:
-
ISO 委员会称其为“永不溢出”。
-
@HansPassant:任何人,无论他们是否是 ISO 委员会,在编写标准文档时都应该准确地使用技术术语。溢出的技术定义是计算结果的量级太大而无法以所选类型表示。 C 中的整数溢出是未定义的行为,但无符号整数不能溢出——这是一个非常重要的说明,如果没有它,有些人可能会认为无符号算术可以例如发出信号。有符号溢出确实在某些平台 (MIPS) 上引发信号(崩溃)。
标签: c gcc 32bit-64bit unsigned