位段和位域

文章介绍了C语言中的位域概念,如何在结构体中定义和使用位域以节省内存空间,并讨论了大小端存储模式。同时,阐述了内存对齐的重要性以及它如何影响位域的存储布局。通过示例代码展示了位域结构可能导致的实际存储结果与预期的不同,并解释了编译器在内存对齐方面的角色。
摘要由CSDN通过智能技术生成

参考资料:位域(位段)用法,对齐机制_位域操作_~QwQ~的博客-CSDN博客

位域是指:数据在存储时不需要一个完整的字节,只需要占用一个或者几个二进制位,为了更好的使用内存空间,C语言提供了位域这种数据结构

在定义结构体时直接指定某个成员变量占用的二进制位数(BIT)

在 : 后面数字来限定成员变量占用的位数

#include <stdio.h>
#include <stdint.h>

typedef struct {
	uint8_t value_1 : 1;
	uint8_t value_2 : 3;
	uint8_t value_3 : 4;
}BitUnion;

int main() {
	BitUnion data;
	data.value_1 = 1;
	data.value_2 = 3;
	data.value_3 = 10;
	printf("data = 0x%x, sizeof_data = %d", data, sizeof(data));
	return 0;
}

在上面给定的位域结构中,高位为value_1,但是这里也有大段存储和小段存储的区别;
这里插播一下大小端存储的简单介绍:大小端存储是计算机用于处理多字节数据的不同方式,在内存中存储多字节数据时,字节的存储习惯
大端存储是指(Big-endian)将多字节数据的高位字节存储在低地址,低位字节存储在高地址,就是从左边往右边读

小端存储是指(Little-endian)将多字节数据的低位字节存储在低地址中,高位字节存储在高地址中,就是从右边往左边读。
大端存储和小端储存的选择一般是由计算机体系结构决定的,X86架构使用小端存储,在arm架构使用的是大端存储。

参考文献:存储概念|详解大小端存储_大端存储和小端存储_DADONGOOO的博客-CSDN博客

 如上示例所示:value_1、value_2、value_3分别使用1个bit位、3个bit位、4个bit位,共使用了8个bit即一个字节
打印结果位为 :data = 0xa7, sizeof_data = 1

 位域的对齐:内存对齐机制

计算机内存是以字节为单位进行划分的,CPU通过地址总线访问内存时,一次能处理多少字节的数据就会让地址总线读几个字节的数据,32位的CPU一次处理4字节的数据,每次就从内存中读取4字节的数据,少了浪费主频,多了没有哟个。64位的处理器每次读取8字节。

对于程序中变量来说,变量最好位于一个寻址步长范围内,这样一次就可以读取到变量的值,如果跨步长存储,就需要读取两次,然后拼接数据,效率低下。

内存对齐与硬件相关,但是决定对齐方式是编译器,可以通过编译器修改。

#include <stdio.h>
#include <stdint.h>

typedef struct {
	uint8_t value_1 : 4;
	uint8_t value_2 : 8;
	uint8_t value_3 : 4;
}BitUnion;

typedef struct {
	uint8_t value_1 : 4;
	uint8_t value_2 : 4;
	uint8_t value_3 : 8;
}BitUnion1;

int main() {
	BitUnion data;
	BitUnion1 data1;
	memset(&data, 0 ,sizeof(data));
	memset(&data1, 0, sizeof(data1));

	data.value_1 = 0xf;
	data.value_2 = 0xff;
	data.value_3 = 0xf;
	uint8_t* P_data = (uint8_t*)&data;
	for (uint8_t i = 0; i < sizeof(data); i++) {
		printf("data[%d] = 0x%x\r\n", i, P_data[i]);
	}

	data1.value_1 = 0xf;
	data1.value_2 = 0xf;
	data1.value_3 = 0xff;
	uint8_t* P_data1 = (uint8_t*)&data1;
	for (uint8_t i = 0; i < sizeof(data1); i++) {
		printf("data[%d] = 0x%x\r\n", i, P_data1[i]);
	}
	return 0;
}

上示例 BitUnion 与预期设计有误的原因是由位域的具体存储规则导致的:
当相邻成员的类型相同时,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;
如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。
 

位段:

位段也叫位域,位段会在结构体的基础规定每个成员变量的大小,大小的单位是二进制位。

在有些信息存储时,并不需要占用一整个字节,而只需要一个或几个二进制位的大小空间,例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值