题目:获取0x12345678各个字节
方法一:结构&联合
#include <stdio.h>
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
union bit32_data
{
uint32_t data;
struct
{
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
}byte;
};
int main(void)
{
union bit32_data num;
num.data = 0x12345678;
printf("byte0 = 0x%x\n", num.byte.byte0);
printf("byte1 = 0x%x\n", num.byte.byte1);
printf("byte2 = 0x%x\n", num.byte.byte2);
printf("byte3 = 0x%x\n", num.byte.byte3);
return 0;
}
为什么在联合体中 uint32_t data 数据可以通过联合体中的结构体byte一个一个取出来呢?
因为联合体的特点就是它的成员共用一块内存空间,因此可以通过不同的成员来访问相同的内存地址。
在这个联合体中,data 和 byte 是联合体的两个成员。data 是一个32位的无符号整数,byte 是一个嵌套结构体,包含了4个8位的无符号字符。
当使用 num.data = 0x12345678; 将一个32位的数据赋值给 data 成员时,联合体的内存空间会被相应的数据填充。
由于联合体的成员共用同一块内存空间,因此可以通过访问 byte 结构体的成员来访问相同的内存位置。在这段代码中,通过 num.byte.byte0、num.byte.byte1、num.byte.byte2 和 num.byte.byte3 分别访问了联合体内存中的不同字节。
通过联合体的特性,可以方便地将整数拆分成字节,或将字节组合成整数。
方法二:移位操作(较为常用)
#include <stdio.h>
#define BYTE0(x) ((x >> 0) & 0x000000ff) /* 获取第0个字节 */
#define BYTE1(x) ((x >> 8) & 0x000000ff) /* 获取第1个字节 */
#define BYTE2(x) ((x >> 16) & 0x000000ff) /* 获取第2个字节 */
#define BYTE3(x) ((x >> 24) & 0x000000ff) /* 获取第3个字节 */
int main(void)
{
unsigned int data = 0x12345678;
printf("byte0 = 0x%x\n", BYTE0(data));
printf("byte1 = 0x%x\n", BYTE1(data));
printf("byte2 = 0x%x\n", BYTE2(data));
printf("byte3 = 0x%x\n", BYTE3(data));
return 0;
}
这种方法使用了宏定义来获取一个32位整数的不同字节。通过右移和按位与操作,可以提取出整数中的每个字节。
BYTE0(x) 宏定义通过将整数 x 右移0位,然后与掩码 0x000000ff 进行按位与操作,获取到整数的第0个字节。
BYTE1(x) 宏定义通过将整数 x 右移8位,然后与掩码 0x000000ff 进行按位与操作,获取到整数的第1个字节。
BYTE2(x) 宏定义通过将整数 x 右移16位,然后与掩码 0x000000ff 进行按位与操作,获取到整数的第2个字节。
BYTE3(x) 宏定义通过将整数 x 右移24位,然后与掩码 0x000000ff 进行按位与操作,获取到整数的第3个字节。
这种通过宏定义来提取字节的方式与使用联合体的方式相比,可以更方便地获取整数中的字节,而无需定义额外的结构体和联合体。