C语言之位域

本文深入探讨了C语言中位域的使用方法及其注意事项。通过一个具体的结构体定义实例,详细解析了位域如何在内存中布局,并展示了如何通过位操作获取位域中的值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

走读代码,再次加深自己对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。

### C语言结构体的使用方法和特性 #### 的基本概念 在C语言中,(Bit Fields)是一种特殊的数据结构,它允许程序员在一个字节内定义多个二进制字段。这使得可以在有限的空间内存储多个布尔值或枚举值[^1]。 #### 定义的方式 通过在结构体内声明成员变量并指定其宽度来实现。基本语法如下: ```c struct { unsigned int member1 : n1; unsigned int member2 : n2; } yourStructName; ``` 其中 `unsigned int` 表示成员的数据类型,可以是 `signed int`, `unsigned int` 或 `_Bool`;而冒号后的数字指定了该成员占据多少个比特[^4]。 #### 实际应用案例 下面是一个具体的例子展示了如何创建包含不同长度的结构体: ```c typedef struct _net_pro_cdu { unsigned char acs : 4; // 占用前四 unsigned char : 0; // 不占任何, 起分隔作用 unsigned char ace : 4; // 接着占用后面的四个置 unsigned char dve : 4; // 新的一组四比特序列 } Ncdu; ``` 这里定义了一个名为Ncdu的新类型,内部有三个分别占有4bit空间的成员acs、ace以及dve,并且还有一个匿名零宽用来强制结束当前字节边界上的填充[^3]。 #### 平台依赖性与移植注意事项 值得注意的是,尽管能够有效地利用内存资源,但由于编译器之间存在差异,对于相同代码片段所产生的实际布局可能有所不同。这意味着当涉及到跨平台开发时,应当特别注意确保程序逻辑不会受到这种不确定性的负面影响[^2]。 #### 组合运用——联合体配合 除了单独作为结构体的一部分外,还可以将与其他高级特性结合起来使用。比如把放在联合体内可以让同一块物理地址既能按整体读写又能逐操作,从而进一步增强了灵活性[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值