我正在尝试从存储在int变量中的十六进制值中提取4个字节。
我的想法是通过使用右移运算符(>>)将所需字节“推”到末尾,然后将AND运算符与0xFF值一起使用,以仅获取值的最后8位。它可以使用数字值(例如73)正常工作,但不能使用a-f(例如3f)值。我曾尝试对printf使用不同的格式,例如%02x,并且还尝试将AND运算符的掩码更改为0x000000FF。
int variable = 0x12cd34f4;
char byte0, byte1, byte2, byte3;
byte0 = (char)(variable & 0xFF);
byte1 = (char)((variable >> 8) & 0xFF);
byte2 = (char)((variable >> 16) & 0xFF);
byte3 = (char)((variable >> 24) & 0xFF);
printf("%x\n",byte0);// prints fffffff4
printf("%x\n",byte1);// prints 34
printf("%x\n",byte2);//prints ffffffcd
printf("%x\n",byte3);//prints 12
我希望它为字节0打印 f4 ,为字节1打印 34 ,为字节2打印 cd ,并为 12 打印字节3,但字节0的实际输出是 fffffff4 和字节2 ffffffcd 。我不明白为什么要添加这些F值,以及如何摆脱它们。
答案 0 :(得分:3)
char
可以是有符号的,也可以是无符号的,这取决于系统(并且可能还取决于编译器选项)。
在您的情况下,显然是signed
。 0x80
和0xFF
之间的值(不仅是从0xA0
开始的值!)已设置了位#7,并被解释为有符号值(例如0xFF为-1,0xF0为-16)等)。
将它们扩展到int
时(调用printf()
时会发生这种情况),它们会被符号扩展(这就是F
的来源),因此保留其“解释值” ”。但是,printf()
被告知再次将它们视为无符号,因此-16表示为0xFFFFFFF0
。
分别使用unsigned char
。 uint8_t
或在呼叫& 0xFF
时添加printf()
。
答案 1 :(得分:2)
只需将 char 强制为 unsigned 即可:
#include <stdio.h>
int main()
{
int variable = 0x12cd34f4;
unsigned char byte0, byte1, byte2, byte3;
byte0 = (char)(variable & 0xFF);
byte1 = (char)((variable >> 8) & 0xFF);
byte2 = (char)((variable >> 16) & 0xFF);
byte3 = (char)((variable >> 24) & 0xFF);
printf("%x\n",byte0);
printf("%x\n",byte1);
printf("%x\n",byte2);
printf("%x\n",byte3);
}
编译和执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
f4
34
cd
12
请注意,当一个字符有8位时,& 0xFF
就没用了
答案 2 :(得分:2)
首先,%x
格式说明符本身没有任何修饰符,用于类型unsigned int
,显然在您的系统上是32位。
字节F4
和CD
的最高有效位为1。这是符号位,因此将其符号扩展为完整的32位(因此FFFFFF
),然后将其打印出来。
观察到,当您将它们打印为%d
时,您也会在播放中看到符号位:
-12
52
-51
18
要解决此问题,您可以使字节类型为unsigned char
,对每个printf
参数使用0xFF
进行按位处理,并使用 correct unsigned char
以十六进制表示的格式说明符,%hhX
。
答案 3 :(得分:2)
您的字节变量声明为char
,在大多数实现中,该变量已签名。当您将这些值传递给printf
时,它不知道所传递内容的确切类型,因为它是可变函数。因此,char
参数被提升为int
。而且由于您的值是负数,因此在促销过程中会扩展符号。
将这些变量的类型更改为unsigned char
。然后将正值提升为int
时,将没有符号扩展名。