2

这个话题在很多情况下都被大量讨论过。当我搜索并阅读一些帖子时。我被以下帖子弄糊涂了。

C中的有符号到无符号转换 - 它总是安全的吗?

以下是原始问题。

unsigned int u = 1234;
int i = -5678;
unsigned int result = u + i;

答案只是引用了“6.3.1.8 通常的算术转换”第 3 点,即

否则,如果无符号整数类型的操作数的等级大于或等于另一个操作数类型的等级,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。

但是,如果我的理解是正确的,那么应该考虑“通常的算术转换”之前进行整数提升。

规则是

如果 int 可以表示原始类型的所有值,则该值将转换为 int 。否则,它将转换为 unsigned int 。这些转换规则称为积分促销

因此,这意味着添加是使用有符号 int 类型而不是unsigned int类型完成的。当将负数分配给unsigned int结果时,会发生转换为大值。

我对自己的理解有点不自信。有没有人对那个帖子有类似的困惑?

欢迎任何回复或评论。提前谢谢!

杰夫

4

3 回答 3

3
unsigned int result = u + i;

我们有一个加法运算符。具有算术类型操作数的加法运算符首先执行通常的算术转换。

通常的算术转换分两步完成:

第一个整数整数提升应用于每个操作数:

  • uint未按原样提升unsigned int
  • i已经是了int,没必要宣传int

由于操作数实际上具有等于 的类型等级int,因此不执行整数提升。

其次,将操作数带入通用类型。常见的类型是unsigned int

  • u已经unsigned int
  • i是类型int并转换为unsigned int

在通常的算术转换之后,将 type 的两个值unsigned int相加并将结果分配给result.

于 2014-02-12T10:41:54.217 回答
2

但是,如果我的理解是正确的,那么应该在考虑“通常的算术转换”之前进行整数提升。

正确,但整数提升规则定义的整数提升仅适用于小整数类型,例如 char 和 short。你只引用了一半的段落,这可能会让你感到困惑。让我引用整个段落:

C11 6.3.1.1/2

可以在可以使用 int 或 unsigned int 的表达式中使用以下内容:

  • 具有整数类型(int 或 unsigned int 除外)的对象或表达式,其整数转换等级小于或等于 int 和 unsigned int 的等级。

  • _Bool、int、signed int 或 unsigned int 类型的位域。

如果 int 可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为 int;否则,它将转换为无符号整数。这些被称为 整数促销。整数提升不会改变所有其他类型。

所以整数提升不适用于intor unsigned int,因为它们没有较低的转换等级。

所以,这意味着添加是用有符号整数类型而不是无符号整数类型完成的。当将负数分配给 unsigned int 结果时,会发生转换为大值。

不正确,由于通常的算术转换,加法是在 usigned int 上完成的。

于 2014-02-12T11:18:30.343 回答
0

我将使用十六进制表示来解释这个问题......

假设一个int变量的大小是 32 位:

  • +1234 = 0x000004D2
  • -5678 = 0xFFFFE9D2

执行时a+b,它们中的每一个如何表示(或)并不重要。如果将上面的两个值相加并将结果存储在一个变量中,那么它将保存一个值 0xFFFFEEA4,而不管每个操作数的符号如何:signedunsignedint

  • 如果输出变量是signed,那么它将被视为(在其他操作中)-4444。
  • 如果输出变量是unsigned,那么它将被视为(在其他操作中)为 4294962852。
于 2014-02-12T10:59:19.877 回答