【问题标题】:Let int8_t num = -1. Why does printf("%u", num) overflow to T_MAX32 instead of T_MAX8?让 int8_t num = -1。为什么 printf("%u", num) 会溢出到 T_MAX32 而不是 T_MAX8?
【发布时间】:2016-10-20 01:43:22
【问题描述】:

int8_t 是一个 8 位有符号整数。因此,它的值在 [-128...127] 范围内的任何位置。

int8_t num = -1;
printf("%u",num);

输出:

4294967295

有人可以给我一个提示吗?

【问题讨论】:

    标签: c


    【解决方案1】:

    您的程序行为未定义。

    %u 不能用作 int8_t 的格式说明符,因为它是有符号类型,而 %u 用于无符号类型。

    改用 %d,并依靠 C 标准保证将 num 自动提升为 int 类型。

    【讨论】:

    • 更具体地说,printf 格式说明符不转换参数类型。它们需要一个类型与说明符匹配的参数,并将其转换为字符串表示形式以供输出。
    【解决方案2】:

    正如其他人所提到的,对printf 使用不正确的格式说明符是undefined behavior。您所经历的行为不能依赖于在不同编译器甚至同一编译器的不同版本之间保持一致。

    话虽如此,这就是最有可能发生的事情。

    printf 在第一个参数之后的任何参数都是未指定的类型。所以当num 被传递给它时,它不能进行精确的类型检查。最终发生的是num 的值被提升为int 类型。

    来自C standard 的第 6.3.1.1 节:

    2 可以在表达式中使用intunsigned int 时可以使用以下内容:

    — 整数类型的对象或表达式 (intunsigned int 除外),其整数转换等级为 小于或等于intunsigned int 的等级。

    ——_Boolintsigned intunsigned int 类型的位字段。

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

    因为num 是在可以使用int 的上下文中使用的,所以它在函数调用中的值被提升为int

    假设 32 位 int 和 2 的补码表示负数,原始二进制表示 11111111 将转换为 11111111 11111111 11111111 11111111。如果使用 %u 格式说明符打印,则假定此表示是无符号的,因此会打印 4294967295

    如果您使用 %d 格式说明符,它需要一个带符号的值,它会打印 -1

    不过,重申一下,您看到的是未定义的行为。其他机器/编译器/优化设置可能会产生不同的结果。

    【讨论】:

      【解决方案3】:

      为了打印int8_t,C 标准提供了来自<inttypes.h> 的格式说明符宏PRIi8

      printf("%" PRIi8, num);
      

      尽管由于 C 的 默认参数提升%d 可以很好地用于打印 int8_t,但您可以简单地将其用于 所有 签名类型。您也可以在POSIX documentation 中查看其他固定宽度类型的格式说明符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-05
        • 1970-01-01
        • 2012-01-10
        相关资源
        最近更新 更多