如何从int变量中提取字节(存储在int变量中的十六进制值)?

时间:2019-02-07 16:29:06

标签: c hex bitwise-operators

我正在尝试从存储在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值,以及如何摆脱它们。

4 个答案:

答案 0 :(得分:3)

char可以是有符号的,也可以是无符号的,这取决于系统(并且可能还取决于编译器选项)。

在您的情况下,显然是signed0x800xFF之间的值(不仅是从0xA0开始的值!)已设置了位#7,并被解释为有符号值(例如0xFF为-1,0xF0为-16)等)。

将它们扩展到int时(调用printf()时会发生这种情况),它们会被符号扩展(这就是F的来源),因此保留其“解释值” ”。但是,printf()被告知再次将它们视为无符号,因此-16表示为0xFFFFFFF0

分别使用unsigned charuint8_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位。

字节F4CD的最高有效位为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时,将没有符号扩展名。