C语言结构体之位域

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

例如:

struct p
{
  int a:8;
  int b:2;
  int c:6;
}data; 
在内存中即:

高位 0000 |0000 00|00|0000 0000|  低位

                       c         b          a

这里有几点需要说明:

1.位域的大小不能超过所定义的数据类型,比如int是32位,若定义int a:33则编译器会报错error C2034:“p::a”:位域类型对位数太小

2.如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

3.如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

4.如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;

下面举一些例子来佐证:

struct p
{
  char a:7;
  char b:2;
  char c:6;
}data; 

高位 0000 |0000 00|00 0|000 0000|  低位 (a占去了8bit中的7bit,剩下的1bit放不下b,所以b放入新的单元)

                       c         b          a

struct p{
    short a:7;
    short b:2;
    short c:6;
}data;

此时情况则不同,因为short型有16位,abc都可以放下

高位 0000 |0000 00|00 |0000 0000|  低位

                       c         b          a

struct p{
    short a:7;
    char b:2;
    char c:6;
}data;
在VC中,即使b可以放在a的后面,但它们的数据类型不一样,故b需要放入新单元

高位0000 00|00| 0000 0000 0|000 0000|  低位

               c      b                              a

转载于:https://www.cnblogs.com/season-peng/p/6713560.html

C语言中的允许在结构体中定义成员变量占用的数,实现对内存中的精确控制,在嵌入式开发、协议解析或硬件寄存器操作中较为有用。以下是关于其操作方法的介绍: ### 的定义 通过在结构体定义中指定成员的大小来创建,在成员类型后添加冒号和数即可。示例代码如下: ```c #include <stdio.h> #include <string.h> int main() { unsigned char puc[4]; struct tagPIM { unsigned char ucPim1; unsigned char ucData0 : 1; unsigned char ucData1 : 2; unsigned char ucData2 : 3; }*pstPimData; pstPimData = (struct tagPIM*)puc; memset(puc, 0, 4); pstPimData->ucPim1 = 2; pstPimData->ucData0 = 3; pstPimData->ucData1 = 4; pstPimData->ucData2 = 5; printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]); return 0; } ``` 上述代码在结构体`tagPIM`中定义了成员`ucData0`、`ucData1`和`ucData2`,分别占用1、2和3 [^5]。 ### 的使用 的使用和结构成员的使用相同,一般形式为:变量名.名,允许用各种格式输出。示例代码如下: ```c #include <stdio.h> int main() { struct bs { unsigned a:1; unsigned b:3; unsigned c:4; } bit, *pbit; bit.a = 1; bit.b = 7; bit.c = 15; printf("%d,%d,%d\n", bit.a, bit.b, bit.c); pbit = &bit; pbit->a = 0; pbit->b &= 3; pbit->c |= 1; printf("%d,%d,%d\n", pbit->a, pbit->b, pbit->c); return 0; } ``` 此代码定义了一个包含结构体`bs`,并对其成员进行赋值和操作,最后输出成员的值 [^2]。 ### 的联合使用 还可以和联合(`union`)一起使用,以实现对同一内存区不同方式的访问。示例代码如下: ```c typedef union { int word; struct { int scan_period :11; int doze_times :5; int reserved31_16 :16; } bit; } SCAN_CTRL1_UN; ``` 上述代码定义了一个联合`SCAN_CTRL1_UN`,其中包含一个整数`word`和一个包含结构体`bit`,可以通过`word`或`bit`来访问同一内存区 [^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值