我是一名 C 程序员新手。我定义了两个变量
int x = 0xffffffff
和 char y = x
,之后我使用 printf("%x\n", y)
函数打印了它;我本以为终端上会出现类似 ff
的内容,但它却在屏幕上打印了 ffffffff
。我想知道当 char 的存储大小为 1 时,char
如何存储 4 个字节的存储空间。
#include <stdio.h>
int main(void) {
int x = 0xffffffff;
char y = x;
printf("%x\n", y);
return 0;
}
实际上这里发生了很多事情。 第一:
int x = 0xffffffff;
整数常量
0xffffffff
的值为 4,294,967,295(即 232-1),类型为 unsigned int
,假设 int
是 32 位。
此
unsigned int
值随后会转换为 int
进行初始化。 这会经历实现定义的转换,在大多数情况下会导致分配值 -1。 该值恰好与二进制补码中的原始值具有相同的表示形式。
然后在这一行:
char y = x;
我们将
y
初始化为值 -1。 该值在 char
的范围内(假设 char
带符号),因此在这种情况下从 int
转换为 char
时,值不会发生变化。 假设采用补码表示,则表示为 0xff
。
然后当你打印时:
printf("%x\n", y);
因为
printf
是一个可变参数函数,所以类型为 y
的参数 char
在传递给函数之前会被 提升 为类型 int
。 和以前一样,两种类型都可以存储值 -1,因此该值保持不变。
%x
格式说明符需要一个unsigned int
类型的参数。 由于传递的是 int
而不是 unsigned int
,这在技术上是未定义的行为,但是有符号/无符号不匹配不太可能在任何实际实现中导致问题。
在这种情况下,
int
值-1具有0xffffffff
的表示形式,当解释为unsigned int
时将具有该值,因此ffffffff
就是打印的内容。
所以回答你的问题:
当一个char的存储大小为1时,一个char如何存储4个字节的存储空间。
事实并非如此。 由于相关类型的转换和表示,它看起来就是这样。
int x = 0xffffffff;
是实现定义的行为,因为在 0xFFFFFFFF
为 32 位的系统上,2^31-1
大于 int
。 int
的大小也是由实现定义的。
如果
char
是 signed
或 unsigned
:,则定义其实现
如果
char
是 signed
,则 char y = x
将值 -1
分配给 x
。 在对 printf()
的调用中,char
被提升为 int
,其大小已实现定义。 在 int
为 32 位的系统上,这被编码为二进制补码 0xFFFFFFFF
(截至 C 2023;之前的版本已实现定义),打印为 ffffffff
。
如果
char
是 unsigned
那么它将打印 ff
。
格式说明符
%x
需要一个 unsigned int
所以你真的应该在打印到明确定义的行为之前将其转换为这样。 无论哪种情况,%x
都不会生成0x
前缀并输出小写字母。