C “奇怪的领导”;f";打印字符时

C “奇怪的领导”;f";打印字符时,c,printf,C,Printf,大家好,我写了以下代码: union endian { char a; int b; } test; char c; test.b = 0xaabbccdd; c = (char)test.a; printf("0x%x\n", c); printf("0x%x\n", test.b); printf("0x%x\n", test.a); printf("0x%x\n", (char)test.a); 但结果是: 0xffffffdd 0xaabbccdd 0xfffff

大家好,我写了以下代码:

union endian {
    char a;
    int  b;
} test;
char c;

test.b = 0xaabbccdd;
c =  (char)test.a;
printf("0x%x\n", c);
printf("0x%x\n", test.b);
printf("0x%x\n", test.a);
printf("0x%x\n", (char)test.a);
但结果是:

0xffffffdd
0xaabbccdd
0xffffffdd
0xffffffdd

我想知道为什么char变量前面有一些前导的
0xffffff

%x
将其参数解释为
无符号int
。传递到变量函数的整数总是升级为
int
,因此您的有符号
char
值将使用符号扩展升级为有符号
int
s,然后由
%x
解释为
无符号int


您可以通过强制转换为
无符号字符
uint8\u t
%x
将其参数解释为
无符号整数
。传递到变量函数的整数总是升级为
int
,因此您的有符号
char
值将使用符号扩展升级为有符号
int
s,然后由
%x
解释为
无符号int


您可以通过强制转换为
无符号字符
uint8_t
来解决此问题。意外的
FFFFFFFF
来自通过符号扩展将
char
转换为
int
。可变参数,即printf(const char*format,…)中format参数之后的参数,被转换为
int
(如果是较小的整数类型)或
double
(如果是浮点)

建议:

使用未修改的格式说明符
%x
(用于
int
)使用修饰符
hh
,而不是打印
c
test.a
的数值

printf("0x%hhx\n", c);
这将在
0x
之后打印出两个十六进制数字



Ref C117.21.6.1 7“hh指定以下d、i、o、u、x或x转换说明符应用于有符号字符或无符号字符参数(该参数将根据整数升迁进行升迁,但其值应在打印前转换为有符号字符或无符号字符)意外的
FFFFFFFF
来自通过符号扩展将
char
转换为
int
。可变参数,即printf(const char*format,…)中format参数之后的参数,被转换为
int
(如果是较小的整数类型)或
double
(如果是浮点)

建议:

使用未修改的格式说明符
%x
(用于
int
)使用修饰符
hh
,而不是打印
c
test.a
的数值

printf("0x%hhx\n", c);
这将在
0x
之后打印出两个十六进制数字



Ref C117.21.6.1 7“hh指定以下d、i、o、u、x或x转换说明符应用于有符号字符或无符号字符参数(该参数将根据整数升迁进行升迁,但其值应在打印前转换为有符号字符或无符号字符);”

它是有符号字符,请尝试更改为
无符号字符
。它是有符号字符,请尝试更改为
无符号字符
。不会提升值。当您传递一个不够大的变量时,c运行时正在查看变量之外的字节。@user814064:它们实际上正在升级(上转换)。例如,(是的,它是C++引用,但是我现在不能链接到C99标准)。@ USE814064,它是一种将事物作为变量的传递规则。C99规格:函数原型声明器中的省略号表示法会导致参数类型转换在最后声明的参数之后停止。默认参数升级是对尾部参数执行的。”.6.5.2.2/6:“整数升级是对每个参数执行的,具有float类型的参数升级为double。这些被称为默认参数“.6.3.1.1/2:“如果一个int可以表示原始类型的所有值,则该值将转换为int;否则,它将被转换为无符号整数。这些被称为整数提升。“值没有被提升。当您传递一个不够大的变量时,c运行时正在查看变量之外的字节。@user814064:它们实际上正在被提升(上转换)。例如,请参阅,(是的,它是C++引用,但我不能把你现在的C99标准链接起来)。@ USE814064,它是把事物作为变量的传递规则。C99规格:函数原型声明符中的省略号表示法会导致参数类型转换在最后一个声明的参数之后停止。默认参数升级是在尾部参数上执行的。“.6.5.2.2/6:”对每个参数执行整数升级,并且具有float类型的参数升级为double。这些被称为默认参数升级。6.3.1.1/2:如果整数可以表示原始类型的所有值,则该值将转换为整数;否则,将转换为无符号整数。这些称为整数。”