走读代码,再次加深自己对C语言位域的理解。
typedef struct _STRUCT_INFO_TEST
{
uint8_t u8HeaderType : 2;
uint8_t u8ServType : 2;
uint8_t u8Priority : 3;
uint8_t u8Extend : 1;
uint8_t u8Rsv[3];
uint32_t u8Len;
}STRUCT_INFO_TEST;
定义的结构体如上,此处定义的u8Rsv数组,作用仅是位了内存按照4字节对齐。
1)一个位域必须存储在同一个字节,不能跨字节存储。
2)位域在内存中的位置是从低位向高位放的。
3)取地址符不能用在位域上。
直接上代码,简洁明了:
int main()
{
STRUCT_INFO_TEST infoTest;
memset((void *)&infoTest, 0, sizeof(STRUCT_INFO_TEST));
printf("sizeof(infoTest) = %d\n", sizeof(STRUCT_INFO_TEST)); //sizeof(infoTest) = 8
infoTest.u8HeaderType = 3;
infoTest.u8ServType = 2;
infoTest.u8Priority = 6;
infoTest.u8Extend = 1;
infoTest.u8Len = 32;
uint8_t *pu8Data = (uint8_t *)malloc(sizeof(STRUCT_INFO_TEST));
memset(pu8Data, 0, sizeof(STRUCT_INFO_TEST));
memcpy(pu8Data, &infoTest, sizeof(STRUCT_INFO_TEST));
uint8_t u8HeaderType = *pu8Data & 0x03;
uint8_t u8ServType = (*pu8Data & 0xC) >> 2;
uint8_t u8Priority = (*pu8Data & 0x70) >> 4;
uint8_t u8Extend = *pu8Data >> 7;
uint32_t u32Len = *(pu8Data + sizeof(uint32_t));
printf("u8HeaderType u8ServType u8Priority u8Extend u32Len:\n");
printf("%-12u %-10u %-10u %-8u %-6d\n", u8HeaderType, u8ServType, u8Priority, u8Extend, u32Len);
return 0;
}
在VS下,可以看到pu8Data在内存中的布局如下图所示:
即对应的二进制为:
1110 1011 -------->最后两位11对应u8HeaderType字段,中间10对应u8ServType字段,110对应u8Priority字段
0000 0000-------序:,首位1对应占1位的u8Extend字段
0000 0000
0000 0000
0010 0000
0000 0000
0000 0000
0000 0000
在取值时,最后连续几位,可以bit mask。比如对于u8HeaderType,可以直接&0x03。
要前面连续几位,可直接位移。例如对于u8Extend,可以直接右移7位。
要中间某几位,可以先bit mask再位移。例如对于u8Priority字段, (*pu8Data & 0x70) >> 4。