C

时间:2015-09-02 04:49:01

标签: c printf unsigned

我有以下代码:

#include <stdio.h>

int main() {
    unsigned int a = -1;
    int b = -1;
    printf("%x\n", a);
    printf("%x\n", b);

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

    printf("%u\n", a);
    printf("%u\n", b);
    return 0;
}

输出结果为:

ffffffff
ffffffff
-1
-1
4294967295
4294967295

我可以看到根据传递给printf函数的值将值解释为有符号或无符号。在这两种情况下,字节都是相同的(ffffffff)。然后,unsigned单词是什么?

4 个答案:

答案 0 :(得分:12)

int -1分配给unsigned:由于-1不适合[0...UINT_MAX]范围,所以会添加UINT_MAX+1的倍数,直到答案为止范围。在OP的计算机上显然UINT_MAXpow(2,32)-1 or 429496725,因此 a 的值为 4294967295

    unsigned int a = -1;

"%x""%u"说明符需要匹配unsigned。由于这些不匹配,“如果转换规范无效,则行为未定义。  如果任何参数不是相应转换规范的正确类型,则行为未定义。“C11§7.21.6.19。printf说明符不会更改b

    printf("%x\n", b);  // UB
    printf("%u\n", b);  // UB

"%d"说明符需要匹配int。由于这些不匹配,因此更多 UB

    printf("%d\n", a);  // UB

鉴于未定义的行为,不支持结论。

  

两种情况下,字节都相同(ffffffff)。

即使使用相同的位模式,不同的类型也可能具有不同的值。 ffffffff unsigned的值为4294967295.作为int,取决于有符号整数编码,其值为-1,-2147483647或TBD。作为float,它可能是NAN

  

什么是无符号字?

unsigned存储[0 ... UINT_MAX]范围内的整数。它永远不会有负值。如果代码需要非负数,请使用unsigned。如果代码需要可能是+, - 或0的计数,请使用int

更新:为避免编译器发出有关将签名int分配给unsigned的警告,请使用以下内容。这是unsigned 1u被否定的 - 如上所述。效果与-1相同,但传达给编译器直接意图。

unsigned int a = -1u;

答案 1 :(得分:0)

在变量声明中使用unsigned对程序员本身更有用 - 不要将变量视为负数。正如您所注意到的,-14294967295对于4字节整数具有完全相同的位表示。这完全取决于您希望如何对待查看

语句unsigned int a = -1;正在将-1转换为二进制补码,并在a中分配位表示。 printf()说明符xdu显示了变量a中存储的位表示形式如何以不同的格式显示。

答案 2 :(得分:0)

初始化unsigned int a to -1;时,表示您将 2's -1 补充存储到{{{}}的内存中1}}。
这只不过是a0xffffffff

因此,当您使用4294967295格式说明符打印它时,您将获得该输出。

通过指定变量的签名来决定可以存储的值的最小和最大限制。

%x or %u一样:范围来自unsigned int0 to 4,294,967,295:范围来自int

有关签名的更多信息,请参阅this

答案 3 :(得分:-5)

十六进制中,它无法获得负值。因此它显示为 ffffffff

使用未签名版本的优势(当您知道所包含的值将是非负的)时,有时计算机会为您发现错误(程序将&#34; 崩溃 &#34;当负值分配给变量时)。