【问题标题】:Why do I get the same value when printing this int?为什么在打印这个 int 时我得到相同的值?
【发布时间】:2010-10-22 20:31:07
【问题描述】:

所以我只是在修改 C 并想看看是否可以将二进制值分配给整数并使用 printf() 函数输出有符号或无符号值。但是无论我得到相同的输出,我认为与未签名相比,打印有符号的价值只有一半。我正在使用 Code::blocks 和 GCC。

printf() 是否忽略 %i & %u 并使用变量定义?

示例代码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    signed int iNumber = 0b1111111111111111;
    printf("Signed Int : %i\n", iNumber);
    printf("Unsigned Int : %u\n", iNumber);

    return 0;
}

如果我将 int 更改为无符号,结果相同:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    unsigned int iNumber = 0b1111111111111111;
    printf("Signed Int : %i\n", iNumber);
    printf("Unsigned Int : %u\n", iNumber);

    return 0;
}

【问题讨论】:

  • 您确定您的 int 类型只有 16 位宽吗?
  • 请注意,像 0b1111 这样的二进制常量语法不是 ISO 标准 C。
  • 使用uint16_t/int16_t 而不是int,这样您就可以确保填写整个值,包括符号位。
  • 你为什么不直接做signed int iNumber = -1
  • @Donotalo - 我的错误,我的废代码没有意义,所以当我将它粘贴到帖子中时,我“清理”了它,所以它可读/有意义,但我显然忽略了一些“次要的” '详细信息:)

标签: c gcc


【解决方案1】:

我假设charCount 应该是iNumber。这两个程序都有未定义的行为,因为您使用了一次错误的转换说明符。

在实践中(对于大多数实现),printf 依赖于您告诉它要从堆栈中弹出什么;这是必要的,因为它是一个可变参数函数。 va_arg将要弹出的类型作为第二个参数

分配前后程序的位相同。所以printf 指向的是相同的位,不同类型的指针。

%i%u 得到相同结果的原因是最左边的位未设置,因此对于两个说明符都被解释为正数。

最后,您应该注意二进制文字 (0b) 是 GCC 扩展,而不是标准 C。

【讨论】:

  • 谢谢,我将其更改为 0xFFFFFFFF0x7FFFFFFF(使用标准 C 十六进制的 32 位整数)并得到了预期的结果。
【解决方案2】:

因为对于正数,大多数平台上的二进制表示在有符号和无符号之间是相同的。

【讨论】:

  • 适用于有符号整数的正数(因为其他正数不能表示为有符号整数,因此它们(不存在)作为有符号整数的表示不能与其表示相同作为无符号整数) ;-)
  • 其实除了上面的nitpick之外,C标准还要求这个。
【解决方案3】:

首先,您似乎正在打印一个名为 charCount 的东西,没有错误,并且 b 指定数字的方式不是标准 C。我会检查以确保它正在执行您认为的操作.对于指定此类位模式的标准方法,请使用八进制(数字以零开头)或十六进制(数字以零开头和x)格式。

其次,几乎所有的计算机对于正整数和它的无符号等价物都有相同的二进制表示,所以不会有区别。如果数字为负数,则会有所不同,这通常取决于最高有效位。您的ints 可以是 16 位以上的任何大小,但在台式机、笔记本电脑或服务器上,它很可能是 32,而且几乎可以肯定是 32 或 64。

第三,printf() 对您传递给它的数据类型一无所知。当被调用时,它甚至无法知道它的参数的大小,或者有多少。它是从格式说明符中得出的,如果这些说明符与传递的参数不一致,则可能会出现问题。这可能是printf() 最糟糕的事情。

【讨论】:

  • 即使是负数,他在实践中也会得到相同的结果,因为从有符号到无符号的赋值不会改变二进制补码的位模式。
  • @Matthew:假设他正在打印相同的位模式,他会得到不同的负数结果,例如 16 位全位一输入的有符号和无符号分别为 -1 和 65535二进制补码。将一个负数分配给一个无符号数会产生一个大的正数,而我认为将一个大的无符号值分配给一个有符号数是未定义的。
  • 我应该更清楚。我在两个程序之间的意思是一样的。
【解决方案4】:

仅对于高于 0x7FFFFFFF 的值,结果会有所不同,因为在几乎所有系统上,用于标记符号的权重最高的位都是如此。为了在 CPU 内部进行更快的计算,其他位被反转,因此 0xFFFFFFFF 为 -1,0x80000000 为 -MAXINT-1,而 0x7FFFFFFF 为 MAXINT。

【讨论】:

    【解决方案5】:

    您可能有 32 位整数。在这种情况下,这意味着您的 iNumber 的值是 32767,无论它是有符号还是无符号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-11
      • 2012-05-19
      • 2014-04-06
      • 2019-03-01
      • 1970-01-01
      相关资源
      最近更新 更多