【问题标题】:C unsigned int + intC 无符号整数 + 整数
【发布时间】:2018-08-18 15:17:36
【问题描述】:

为什么这段代码会打印"greater than 0"

int main()
{
  unsigned int a = 5;
  int b = -10;
  (a + b) > 0 ? printf("greater than 0") : printf("less than 0");
}

如果我这样做:

printf("%d\n", a + b);

...它打印:

-5 

【问题讨论】:

  • 整数提升规则。
  • printf("%d\n", a + b); 实际上有未定义的行为。 a + b 的结果是 unsigned int 类型,但 "%d" 需要 int 类型的参数。如果值在 but 类型的范围内是可以的,但这里不是这样。

标签: c int unsigned


【解决方案1】:

每当您在 C 中执行任何操作时,参数都会根据“通常的算术转换”规则(规范的第 6.3.1.8 节)进行转换。它们有很多,但就本示例而言,重要的是:

整数提升在两个操作数上执行。然后 以下规则适用于提升的操作数:
如果两个操作数的类型相同,则无需进一步转换。
否则,如果两个操作数都具有带符号整数类型或都具有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。
否则,如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数的类型的等级,然后操作数与 有符号整数类型转换为无符号操作数的类型 整数类型。

intunsigned int 具有相同的覆盖等级,因此每当您对 intunsigned int 执行操作时,int 将转换为 unsigned

在您的情况下,这会导致 b (-10) 的值变得非常大。然后向它添加 5,它仍然非常大(但不足以回绕回零),因此 > 的结果为真。

【讨论】:

  • 你可能也想解释一下 UB。
  • -10 转换为unsigned 时的实际值等于UINT_MAX - 9,其中UINT_MAX<limits.h> 中可用,表示@ 的最大值(实现定义) 987654333@可以代表。此外,a + b 给出正值的原因与换行无关 - 这是因为它的 unsigned 结果永远不会为负。
  • @Peter -- 虽然无符号值永远不会是负数,但它可能为零,因此由于类型原因不能忽略比较 -- 它仍然必须执行(可能在编译时作为一个常量折叠,因为这里所有的操作数都是常量)。
  • @ChrisDodd - 我没有其他建议。给定输入,OP 显然期望输出“小于 0”。在任何情况下,输入都不会产生零结果。
【解决方案2】:

6.3.1.1 Boolean, characters, and integers6.3.1.8 Usual arithmetic conversions(感谢克里斯)

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

...如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数的类型的等级,然后是操作数 带符号整数类型转换为操作数的类型 无符号整数类型。

你的加法涉及到一个unsigned和一个intint不能代表unsigned的所有值,所以将值转换为unsigned int

【讨论】:

    【解决方案3】:

    你的问题

    根据usual arithmetic conversions,默认情况下,您的int 会升级为unsigned int

    [...] 如果具有无符号整数类型的操作数具有秩 大于或等于另一个操作数的类型的等级,则 带符号整数类型的操作数转换为 无符号整数类型的操作数。

    解决方案

    您需要将 a 转换为 int 才能使此三元组按预期工作:

    ((int)a + b) > 0 ? printf("greater than 0") : printf("less than 0");
    

    【讨论】:

      【解决方案4】:

      在您的打印语句中,您将 a 和 b 转换为它们的有符号 int 表示,然后再将它们相加。你这样做不是为了你的条件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-09
        • 2010-09-19
        • 2013-10-02
        • 2014-12-09
        • 1970-01-01
        • 1970-01-01
        • 2012-01-06
        相关资源
        最近更新 更多