我有以下代码
char temp[] = { 0xAE, 0xFF };
printf("%X\n", temp[0]);
为什么输出为FFFFFFAE
,而不仅仅是AE
?
我试过
printf("%X\n", 0b10101110);
输出正确:AE
。
建议?
答案 0 :(得分:2)
您获得的答案FFFFFFAE
是签名char
数据类型的结果。如果你检查了这个值,你会发现它等于-82,其中-82 + 256 = 174,或者是十六进制的0xAE
。
打印0b10101110
甚至174时获得正确输出的原因是因为您直接使用了文字值,而在您的示例中,您首先将0xAE值放在{{1}中如果你想以这种方式想到它,那么这个值就像是“重新解释模128”一样。
换句话说:
signed char
要修复此“问题”,您可以声明您最初使用的相同数组,只需确保使用 0 = 0 = 0x00
127 = 127 = 0x7F
128 = -128 = 0xFFFFFF80
129 = -127 = 0xFFFFFF81
174 = -82 = 0xFFFFFFAE
255 = -1 = 0xFFFFFFFF
256 = 0 = 0x00
类型数组,您的值应按预期打印。
unsigned char
输出:
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char temp[] = { 0xAE, 0xFF };
printf("%X\n", temp[0]);
printf("%d\n\n", temp[0]);
printf("%X\n", temp[1]);
printf("%d\n\n", temp[1]);
return EXIT_SUCCESS;
}
答案 1 :(得分:1)
https://linux.die.net/man/3/printf
根据手册页,%x
或%X
接受unsigned integer
。因此它将从堆栈中读取4个字节。
在任何情况下,在大多数架构下,您都无法传递小于word
(即int
或long
)的参数,在您的情况下它将转换为int.
在第一种情况下,您传递char
,因此会将其投放到int
。两者都是签名的,因此执行签名的强制转换,因此您可以看到前面的FF
。
在你的第二个例子中,你实际上一直在传递int
,所以不会执行强制转换。
如果您尝试:
printf("%X\n", (char) 0b10101110);
您会看到FFFFFFAE
将被打印。
答案 2 :(得分:1)
当您将小于int
数据类型(如char
is)传递给可变函数时(如printf(3)
那样),参数将转换为int
以防万一参数为signed
,如果是无符号,则为unsigned int
。正在做什么并且您观察到的是符号扩展,因为char
变量的最有意义的位是活动的,它被复制到完成{{1}所需的thre字节}。
要解决此问题并将数据保存为8位,您有两种可能:
允许您的int
转换为int(带符号扩展名),然后屏蔽8位及以上的位。
signed char
将您的变量声明为printf("%X\n", (int) my_char & 0xff);
,因此会将其提升为unsigned
。
unsigned int
答案 3 :(得分:0)
此代码会导致undefined behaviour。 %X
的参数必须为unsigned int
,但您提供char
。
未定义的行为意味着任何事情都可能发生;包括但不限于输出中出现的额外F。