C 中的无符号值

Unsigned values in C

我有以下代码:

#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这个词是干什么用的呢?

十六进制中不能得到负值。所以它显示为 ffffffff.

使用无符号版本的优点(当您知道包含的值将是非负数时)是有时计算机会为您发现错误(程序将“负值分配给变量时崩溃”。

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

语句unsigned int a = -1;-1转换成二进制补码,并赋值给a中的位表示。 printf() 说明符 xdu 显示了存储在变量 a 中的位表示在不同格式下的样子。

当你初始化 unsigned int a to -1; 时,这意味着你正在存储 2's -1[=36 的补码=] 到 a.
的内存中 这不过是 0xffffffff4294967295.

因此,当您使用 %x or %u 格式说明符打印它时,您会得到该输出。

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

unsigned int一样:范围从0 to 4,294,967,295int:范围从-2,147,483,648 to 2,147,483,647

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

int -1分配给unsigned:由于-1不在[0...UINT_MAX]范围内,所以添加UINT_MAX+1的倍数直到答案在范围内。显然 UINT_MAX 在 OP 的机器上是 pow(2,32)-1 or 429496725 所以 a 的值是 4294967295.

unsigned int a = -1;

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

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

"%d" 说明符需要一个匹配的 int。由于这些不匹配,更多 UB.

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

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


both cases, the bytes are the same (ffffffff).

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

what is unsigned word for?

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


更新:为了避免将带符号的 int 分配给 unsigned 时出现编译器警告,请使用以下内容。这是一个 unsigned 1u 被否定 - 上面定义明确。效果与 -1 相同,但向编译器传达了直接意图。

unsigned int a = -1u;