当前位置:   article > 正文

C语言之位域(位段)入门详解_c语言位域

c语言位域

一、引言

信息处理中,有些信息在存储时,并不需要占用一个完整的字节,而只需占一个或几个比特位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进制位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。
所谓“位域”是把一个字节中的比特位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。位域在本质上就是一种结构类型, 不过其成员是按二进制位分配的。

二、位域

1.位域的定义
位域是通过结构体来定义的,相比较普通的结构体,位域的成员需要明确标注其所占比特位的长度。
位域定义的基本语法如下:

struct 位域结构体名 
{
	位域列表 
};
  • 1
  • 2
  • 3
  • 4

其中位域列表的形式为:

     类型说明符  位域名 : 位域长度;
  • 1

例如:

 struct BitField
{
	char a:8;
	char b:2;
	char c:5;
}; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

该结构体定义的就是位域(位段),位域a占用8个比特位,位域b占用2个比特位,位域c占用5个比特位。
位域的总长度和域变量定义的类型有关,是存储单元类型长度的倍数。
2.位域变量的定义
位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明、同时定义说明、直接说明这三种方式。
例如:

struct BitField
{
	char a:8;
	char b:2;
	char c:5;
}weiyu; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

weiyu为BitField变量,共占两个字节。
3.位域的注意事项
1)一个位域必须存储在同一个存储单元中,不能跨两个存储单元。
2)一个存储单元所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct bf
{
	unsigned char a:4;
	unsigned char :0; /*空域*/
	unsigned char b:4; /*从下一单元开始存放*/
	unsigned char c:4;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

struct bf
{
	 unsigned  char a:5;
	 unsigned  char b:2; 
	 unsigned  char c:4;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
sizeof(struct bf) =  2 //该位域总长度为2个字节
  • 1

3) 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k
{
  int a:1;
  int :2; /*该2位不能使用*/
  int b:3;
  int c:2;
}; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4)位域列表中,尽可能不要出现不同类型的域,否则,不同的编译器下得到的位域的长度将不一致。
4.位域的使用
位域的使用和结构成员的使用相同,其一般形式为:

 位域变量名·位域名
  • 1

位域允许用各种格式输出。
5.位域在内存中存储模式
不同的芯片存储次序是不同的,对于Intel芯片,是按照从低位开始存储的,而对于Motolola芯片则正好相反。因此在使用不同芯片之间进行数据传输使用位域存储的数据的时候,必须知道是否是相同的芯片之间的数据传输,因为在信息的接收端要确保按照正确的次序读取相应的位域,否则将会发生不可预知的错误!!!

三、位域示例

Demo1:对某位域分别赋值,之后对位域进行不同的赋值或者位运算,并分别向屏幕输出位域。
1)参考代码

#include"stdio.h"
struct bf
{
	unsigned char a:1;
	unsigned char b:3;
	unsigned char c:3;
};
int main()
{
	bf bit, *pbit;
	bit.a = 1;
	bit.b = 7;
	bit.c = 2;
	printf(" %d,%d,%d\n",bit.a,bit.b,bit.c);
	pbit = &bit;
	pbit->a = 0;
	pbit->b &= 0x5;
	pbit->c |= 0x5;
	printf(" %d,%d,%d\n",pbit->a,pbit->b,pbit->c);
	printf( " length of bitfield : %d", sizeof( bf ) );
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2)第一次给位域赋值后,内存的状态

在这里插入图片描述
0位存储的是位域a,占1个二进制位,其值是1
1-3位存储的是位域b,占3个二进制位,其值是7
4-6位存储的是位域c,占3个二进制位,其值是2
3)运行结果
在这里插入图片描述
Demo2:对位域整体进行赋值,之后分别输出每个位域
1)参考代码

#include"stdio.h"
struct BF
{
	unsigned char a:5;
	unsigned char b:2;
	unsigned char c:4;
};
int main()
{
	BF *val;
	unsigned short aa = 1000;//1111101000
	val = ( struct BF * )&aa;
	printf(" BF.a = %d\n", val->a);
	printf(" BF.b = %d\n", val->b);
	printf(" BF.c = %d\n", val->c);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2)内存状态
在这里插入图片描述
3)运行结果
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/515880
推荐阅读
相关标签
  

闽ICP备14008679号