关于 C 中无符号类型的说明

Clarifications about unsigned type in C

你好,我正在学习 C,有些东西我不太明白。 首先有人告诉我,如果我这样做:

unsigned int c2 = -1;
printf("c2 = %u\n", c2);

它会输出255,根据这个table:

但我得到了一个奇怪的结果:c2 = 4294967295

现在更奇怪的是这有效:

unsigned char c2 = -1;
printf("c2 = %d\n", c2);

但我不明白,因为 charchar 为什么它甚至打印任何东西?由于此处的说明符是 %d 而不是 %u,因为它应该用于无符号类型。

在 C 中整数可以有多种表示,因此有多种存储大小和取值范围 请参阅下面的 table 以了解更多详细信息。

在此声明中

unsigned char c2 = -1;

-1 的内部表示被截断为一个字节并解释为无符号字符。即对象 c2 的所有位都已设置。

在本次通话中

printf("c2 = %d\n", c2);

具有 unsigned char 类型的参数被提升为类型 int 并保留其值 255。该值作为整数输出。

这是声明吗

unsigned int c2 = -1;

没有截断。通常占用 4 个字节的整数值 -1(根据 int 类型的大小)被解释为所有位都设置的无符号值。

所以在这次通话中

printf("c2 = %u\n", c2);

输出了unsigned int类型的最大值。它是最大值,因为内部表示中的所有位都已设置。从有符号整数类型到更大的无符号整数类型的转换保留将其传播到无符号整数对象宽度的符号。

以下代码:

unsigned int c2 = -1;
printf("c2 = %u\n", c2);

永远不会打印 255。您正在查看的 table 指的是 8 位无符号整数。 C 中的 int 需要至少 16 位才能符合 C 标准(UINT_MAX 在第 22 页第 §5.2.4.2.1 段中定义为 2^16-1 here).因此,您将看到的值将比 255 大得多。最常见的实现对 int 使用 32 位,在这种情况下,您将看到 4294967295 (2^32 - 1)。

您可以通过执行 sizeof(type_or_variable) * CHAR_BIT 检查系统上任何类型的变量使用了多少位(CHAR_BITlimits.h 中定义并表示每个字节的位数, 这又是大多数时候 8).

获取 255 作为输出的正确代码是:

unsigned char c = -1;
printf("c = %hhu\n", c);

其中 hh 前缀说明符表示(来自 man 3 printf):

hh: A following integer conversion corresponds to a signed char or unsigned char argument, or a following n conversion corresponds to a pointer to a signed char argument.

任何其他只是实现定义或更糟糕的未定义行为。