【发布时间】:2017-09-06 06:25:20
【问题描述】:
C 和 C++ 标准规定,在相同级别的有符号整数和无符号整数之间的二进制运算中,有符号整数被强制转换为无符号整数。由此引起的关于 SO 的问题很多......我们称之为奇怪的行为:unsigned to signed conversion、C++ Implicit Conversion (Signed + Unsigned)、A warning - comparison between signed and unsigned integer expressions、% (mod) with mixed signedness 等。
但是这些都没有给出任何理由说明为什么标准会采用这种方式,而不是强制转换为有符号整数。我确实找到了一位自称为大师的人,他说这样做显然是正确的,但他也没有给出任何理由:http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/。
查看我自己的代码,无论我在哪里组合有符号和无符号整数,我总是需要从无符号转换为有符号。有些地方无关紧要,但我还没有找到一个可以将有符号整数转换为无符号的代码示例。
在哪些情况下可以正确执行无符号转换?为什么标准是这样的?
【问题讨论】:
-
假装它是 1970 年代 - 想想迪斯科。有符号有 3 个品种,2 的补码,1 的补码和有符号的量级。无符号只有 1 种。关于混合类型的规则已经够糟糕了。然而,通过转为有符号类型,结果变得更加复杂,因为规则需要 3 个变体目的地,而不是转为无符号时的 1 个。
-
@chux,我认为推理可能与此有关。但是为什么你需要三个规则呢?如果将 -1 转换为无符号可以在 3 种有符号整数中以单一、明确的方式完成,为什么不能以单一、明确的方式将
0xFFFF转换为无符号? (请注意,我正在考虑 16 位整数,因为它是 70 年代和所有。) -
C 语言 - 正如其他人所说的那样,发明了这条规则 - 只有少数数据结构 - 裸数组、结构和指针 - 与当时的简单机器寻址模式相匹配- 诸如索引、间接、基础+位移、基础+位移+索引之类的东西。现在.. 确实,当时标准机器中的索引寻址模式将采用有符号整数......但当时的程序员并不经常使用负数来索引......而且他们 确实在他们的 16 位机器上需要 2 倍的无符号范围(尤其是在单词字段中)
-
Chris:该标准仅保证无符号值具有与具有相同等级的有符号值一样多的值位,而不是将符号位重新解释为值位。因此,您可以通过将无符号值的符号位强制为正来处理非 2s 补码架构,从而将可表示值的范围限制为有符号类型中可表示的正值范围。这使得两个转换都变得简单(无符号到有符号变为无操作或掩码)。但这也意味着将始终选择带符号的类型进行标准转换。
-
“我总是需要从无符号转换为有符号。” - 请记住,当无符号的值大于有符号类型的最大值时,这是不可移植的。编译器发出警告是有原因的;通过在这里投射,您是在说“哦,这永远不会发生”