19_09_13 关于c语言中位域的理解

在实际接触的C语言项目中,我们会发现很多时候都用到了位域。初次听到时可能有些模糊,但其实是很好理解的,以下是经过参考各类资料和大牛的说法后本人对位域的一些理解。
如有问题,欢迎告知,感谢之至。

1.什么是位域?

简单的理解,就是“按位存储”。
实际在c语言中,不同的编译器下,我们对各种类型的变量进行不同字节的存储。百度百科对字节是这么说明的:最常用的字节是八位的字节,即它包含八位的二进制数。(有兴趣的小伙伴们可以自行了解)。这里可简单理解为基本上每个字节都是占8位。
但是有时候我们所需要使用的位数并不需要那么多,比如:开关变量我们设置开为1,关为0,其实只要用一位二进制位就能够实现。因此为了节约存储空间和使处理起来方便。我们便把一个字节分开来,形成不同大小的位域,每个位域有一个域名。这样就可以实现将不同的对象用一个字节来存储。

2.怎么定义位域?

位域的定义类似于结构体的定义(好几种,可参考结构体的定义及声明)。
结构体的一种定义形式为:
struct 结构体名
{
结构体成员列表;
};

类似于此,位域也可定义为:
struct 位域名
{
位域列表;
};

位域列表的定义形式为:
类型说明符 位域名:位域长度;
需要注意的是,位域名后面用“:”(冒号)

3.一个字节中各个位域的位置顺序?

即我们在同一个字节里定义位域的时候,是按照从低到高位,还是从高到低位来存储的呢?我们来做一个实验。

#include<stdio.h>
union o{
		struct{
			unsigned char a1:2;
			unsigned char a2:2;
			unsigned char a3:2;
			unsigned char a4:2;
		}in;
		unsigned char test;
	}out;
	
int main(){
	out.test=228;     //二进制为11100100
	printf("a1:%d\n",out.in.a1);
	printf("a2:%d\n",out.in.a2);
	printf("a3:%d\n",out.in.a3);
	printf("a4:%d\n",out.in.a4);
	printf("size:%d\n",sizeof(out));
	return 0;
} 

在联合体out内定义结构体in和变量test,使他们在同样内存里存储。设置无符号char型变量test值为228,其二进制数为11100100,然后分别输出:
在这里插入图片描述
发现对应关系如下:

进制a4a3a2a1
十进制3210
二进制11100100

也就是说,按照我们定义的顺序,再同一个字节里面,是从低位到高位开始存储的。1

4.跨字节位域的存储?

在当前字节所含位数少于我们所需要的位数时,又是怎么存储的呢?我们先来看两段段代码:

#include<stdio.h>
struct ab{
	unsigned char a:2;
	unsigned char b:4;
}aa;
;
int main(){
	printf("%d\n",sizeof(aa));
	return 0;
} 

这是我们在同一个字节里未超出一个字节时,输出是:
在这里插入图片描述

#include<stdio.h>
struct ab{
	unsigned char a:2;
	unsigned char b:4;
	unsigned char c:4;
	
}aa;
;
int main(){
	printf("%d\n",sizeof(aa));
	return 0;
} 

这是超过了一个字节所含位数时,输出是:
在这里插入图片描述
可以发现,当当前的字节存不下时,会从下一个字节开始。且字节大小为位域中最长字节的整数倍。
为了更好理解,当我们把代码改成如下时:

#include<stdio.h>
struct aa{
	unsigned char a:2;
	unsigned char b:4;
	unsigned int c:4;
}aa;
int main(){
	printf("%d\n",sizeof(aa));
	return 0;
} 

会出现这样的结果:
在这里插入图片描述
这是为什么呢?其实,与结构体类似,位域也需要遵循内存对齐的原则。我们首先考虑类型所占用的字节,总的字节大小是最大对齐数的整数倍,所以是4的整数倍。然后才考虑实际每个字节里面具体位域分布(关于结构体的内存对齐感兴趣的可以自行了解)。


  1. 参考地址:https://www.cnblogs.com/maowang1991/p/3656072.html ↩︎

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值