代码
char a;
a = 0xf1;
printf("%x\n", a);
输出
fffffff1
printf()
显示 4 个字节,即我们在 a
中有一个字节。
这种不当行为的原因是什么?
我该如何纠正?
这种不当行为的原因是什么?
这个问题看起来与我回答过的另一个问题“奇怪地相似”;它甚至包含类似的值(0xfffffff1
)。在该答案中,我提供了一些所需的信息,以了解当您将小值(例如
char
)传递给可变参数函数(例如 printf
)时会发生什么转换。没有必要在这里重复这些信息。如果您检查 CHAR_MIN
中的
CHAR_MAX
和 <limits.h>
,您可能会发现您的 char
类型是带符号的,因此 0xf1
不适合作为 char
内部的整数值。 相反,它最终以实现定义的方式进行转换,这对于我们大多数人来说意味着最终可能会导致高位之一成为符号位。当这些值提升为 int
(为了传递到
printf
)时,会发生符号扩展以保留该值(即,值为 -1 的 char
应转换为具有以下值的 int):值 -1 作为 int
,因此示例的底层表示也可能从 0xf1
转换为 0xfffffff1
)。printf("CHAR_MIN .. CHAR_MAX: %d .. %d\n", CHAR_MIN, CHAR_MAX);
printf("Does %d fit? %s\n", '\xFF', '\xFF' >= CHAR_MIN && '\xFF' <= CHAR_MAX ? "Yes!"
: "No!");
printf("%d %X\n", (char) -1, (char) -1); // Both of these get converted to int
printf("%d %X\n", -1, -1); // ... and so are equivalent to these
我该如何纠正?使用适合值
a
的类型声明
0xf1
,例如 int
或 unsigned char
。printf
是一个可变参数函数,因此编译器会尽力但无法检查格式说明符和参数类型之间的严格一致性。
在这里,您将传递带有
char
(整数、十六进制)格式说明符的
%x
。因此该值被提升为有符号整数(因为> 127:负字符和
char
在大多数系统上都有符号,在您的系统上这是肯定的)
要么:
将
a
int
(最简单)将a
unsigned char
(按照BLUEPIXY的建议),以处理促销中的标志将格式更改为 %hhx
hhx
无法识别,即使 hx
是)
达到 printf
之前警告您有问题:
gcc -Wall -Wpedantic test.c
test.c: In function 'main':
test.c:6:5: warning: overflow in implicit constant conversion [-Woverflow]
a = 0xf1;
int a
而不是
char a
,因为 char
是无符号的,只能存储从 0 到 255 的 1 个字节。
而十六进制数需要很多存储空间来存储,而且int
存储大小为2或4字节。所以这里最好使用int
来存储十六进制数。