【问题标题】:Still Questions on integer promotion, conversions in C关于整数提升的问题,C 中的转换
【发布时间】:2014-03-10 15:06:54
【问题描述】:

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

Signed to unsigned conversion in C - is it always safe?

以下是原题。

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

答案简单引用了“6.3.1.8 常用算术转换”第 3 点,即

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

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

规则是

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

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

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

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

杰夫

【问题讨论】:

    标签: c type-conversion integer-promotion


    【解决方案1】:
    unsigned int result = u + i;
    

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

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

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

    • u 未提升为 int,因为它是 unsigned int
    • i已经是int了,不用推广到int

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

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

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

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

    【讨论】:

    • 看来我对上面帖子中的第二条规则有点误解。我的理解是int可以代表u的值,所以,u应该提升为int,而不是unsigned int。错了吗?
    • @Poor 第一步是整数提升,这里提升的操作数在提升前后的类型相同。在第二步中,C 说 (in c99, 6.3.1.8p1) “如果具有无符号整数类型的操作数的等级大于或等于另一个操作数类型的等级,则具有带符号整数的操作数type 转换为无符号整数类型的操作数的类型。” 类型unsigned int 和int 的转换等级相同。这就是i在第二步转换为unsigned int的原因。
    • “由于操作数的类型等级实际上小于..”,您可能的意思是“由于两个操作数的类型等级实际上都等于...”?
    【解决方案2】:

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

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

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

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

    • 如果输出变量是signed,那么它将被视为(在其他操作中)-4444。
    • 如果输出变量是unsigned,那么它将被视为(在其他操作中)4294962852。

    【讨论】:

    • 我相信这不是真的。这不适用于具有 1 的补码或符号/大小的系统。
    【解决方案3】:

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

    正确,但整数提升,如整数提升规则所定义,仅适用于 小整数类型,例如 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; 否则,它将转换为无符号整数。这些被称为 整数促销。所有其他类型都不变整数 促销活动。

    因此整数提升不适用于int 或unsigned int,因为它们的转化排名不低。

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

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

    【讨论】:

    • +1 删除了我的答案,因为它只回答了一半的问题。这个答案应有尽有。
    • @Lundin 你是对的,我忽略了整数提升的条件或者没有完全理解这个条件的含义。陷阱语句是 (int 或 unsigned int 除外)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2016-12-15
    • 1970-01-01
    • 2019-04-19
    相关资源
    最近更新 更多