【问题标题】:Unsigned int in C behaves negativeC中的无符号整数表现为负
【发布时间】:2013-05-24 15:11:07
【问题描述】:

我不明白为什么 unsigned int 的输出对于以下代码是负数。 就像一个有符号的 int。

  uint32_t yyy=1<<31;
  printf("%d\n",yyy);

输出是:

-2147483648

这是-2^31

【问题讨论】:

  • 试试printf("%u\n",yyy);
  • 即使在您调用 printf 之前,如果 int 在您的 C 实现中具有 32 位,则此代码具有未定义的行为。 1&lt;&lt;31 的值溢出 int。您应该使用1u&lt;&lt;31,以便它移动unsigned int

标签: c printf undefined-behavior


【解决方案1】:

%d 的格式说明符需要int,而不是unsigned int,因此代码具有未定义的行为。来自 C99 标准部分 7.19.6.1 的 fprintf 函数

如果任何参数不是相应转换规范的正确类型,则行为未定义。

%u 用于unsigned int

uint32_t yyy=1u<<31;
printf("%u\n",yyy);

输出:

2147483648

【讨论】:

  • 出于可移植性考虑,可以使用以下命令打印 uint32_t(可能大于无符号数):'printf("%"PRIu32"\n", yyy);'
【解决方案2】:

这是因为您的 printf 参数,作为 %d,正在隐式地将您的数字转换为 int。

改用 %u。

【讨论】:

  • 我明白了。谢谢你的回答~
【解决方案3】:

使用%u输出无符号数:

printf("%u\n", yyy);

【讨论】:

    【解决方案4】:

    正如许多人所说,使用%u 标识符。

    原因是printf 无法确定任何额外参数的类型(它们以va_list 的形式给出),因此程序员必须使用格式字符串提供该信息.然后,当您提供%d 时,printf 将调用:

    int val;
    val = va_arg(va_list, int);
    

    并将您的 unsigned int 隐式转换为带符号的。

    【讨论】:

      【解决方案5】:

      因为您将其打印为已签名。请改用%u

      【讨论】:

        【解决方案6】:

        printf 接受可变数量的参数。当您调用它时,编译器会尽职尽责地将它们全部放入堆栈中。因为它是 C,所以没有反射——printf 不能随后推断它收到的东西的类型。在位级别上,您无法初步区分有符号整数和无符号整数或浮点数、适当小的结构、较大结构的一部分等。

        这就是为什么您还必须提供格式字符串的原因。它告诉printf 从堆栈中读取什么类型以及以什么顺序读取。它完全取决于该格式字符串,无法验证它。

        因此,根据已经发布的单行答案,如果您告诉它将字段解释为已签名数量,那么它将被打印为已签名数量。

        【讨论】:

          【解决方案7】:

          整数以Two's Complement 格式存储。这意味着无法仅通过查看值来判断数字是有符号还是无符号。您必须告诉机器您希望它使用哪种表示并自己跟踪它。

          在您的示例中,您告诉机器 jjj 是无符号的(用于类型检查),然后要求 printf() 在格式字符串中使用 %d 将其视为已签名(它无法获取类型信息)。如果你想打印一个无符号整数,请改用%u

          【讨论】:

            【解决方案8】:

            您需要使用unsigned int 格式说明符:

            printf("%u\n",yyy);
                    ^^
            

            printf 使用错误的格式说明符是未定义的行为,这在 C99 草案标准部分 7.19.6.1 中进行了介绍说:

            如果转换规范无效,则行为是 undefined.248) 如果任何参数不是正确的类型 对应的转换规范,行为未定义。

            printfcppreference 页面有一个很好的表格,指定了可用的格式说明符。

            【讨论】:

              猜你喜欢
              • 2021-04-10
              • 2020-10-13
              • 2015-10-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-11-16
              • 2012-01-09
              相关资源
              最近更新 更多