史上最全的C位域总结

此篇文章是转载之史上最全的C位域总结


经过个人查阅相关的资料和理解,现对C语言的位域做一个总结,对于位域的定义我在这里没有多说,我这里主要是对位域有歧义的地方进行系统的总结.我个人觉得总结的比较完整,如有不够完整或有异义的地方大家可以留言指点.
1.位域又叫位段(位字段),是一种特殊的结构成员联合成员(即只能用在结构或联合中),用于指定该成员在内存存储时所占用的位数,从而可以在机内更紧凑地表示数据。
2.位域的使用主要出现在如下两种情况:
 (1)当机器可用内存空间较少而使用位域可以大量节省内存时。如,当把结构作为大数组的元素时。
 (2)当需要把一结构或联合映射成某预定的组织结构时。例如,当需要访问字节内的特定位时。
3.当要把某个成员说明成位域时,其类型只能是int,unsigned int与signed int三者之一(说明:int类型通常代表特定机器中整数的自然长度。short类型通常为16位,long类型通常为32位,int类型可以为16位或32位.各编译器可以根据硬件特性自主选择合适的类型长度.见The C Programming Language中文 P32)。
4.带位域的结构在内存中各个位域的存储方式取决于具体的编译程序;它们既可以从左到右,也可以从右到左存储。
5.在一包含位域说明的强构或联合区分符中也可以同时说明普通成员,例如:
    struct st1
    {
       unsigned a:7;
       unsigned b:4;
       unsigned c:5;
       int      i;     //i是普通成员,这会被存放在下一个字,即字对齐
     };
6.int值不能跨字存放,同样位域也最好不要跨字存放(意思说是说:各位域的分配位数加起来要在16位或32位以内,如果编译器分配int为16位,则加起来要在16位以内,如果加起来大于16位,则最好空出剩余的位域,从下一个字开始分配位域).
7.特殊宽度0或者说长度为0的无名位域有着特殊的用途.它用于指示将其前后的两个位域或成员分开放在两个字中, 即将位于该无名位域后的下一个位域从下一个字开始存放.
8.位域备注:
关于位域还需要提醒读者注意如下几点:
其一,位域的长度不能大于int对象所占用的字位数.例如,若int对象占用16位,则如下位域说明是错误的:
     unsigned int x:17;
其二,由于位域的实现会因编译程序的不同而不同,在此使用位域会影响程序的可移植性,在不是非要使用位域不可时最好不要使用位域.
其三,尽管使用位域可以节省内存空间,但却增加了处理时间,在为当访问各个位域成员时需要把位域从它所在的字中分解出来或反过来把一值压缩存到位域所在的字位中.
其四,位域的位置不能访问,因些不能对位域使用地址运算符号&(而对非位域成员则可以使用该运算符).从而,即不能使用指向位域的旨针也不能使用位域的数组(因为数组实际上就是一种特殊的指针).另外,位域也不能作为函数返回的结果.
最后还要强调一遍:位域又叫位段(位字段),是一种特殊的结构成员或联合成员(即只能用在结构或联合中).

说明:以上大多数文字摘自《ANSI C标准详解》及《The C Programming Language中文第二新版》.在此对以上两本参考书的团体表示感谢.

### C语言的使用方法和特性 #### 定义与声明 在C语言中,是一种特殊的结构体成员,允许程序员指定每个成员占用多少个二进制。这有助于更高效地管理内存资源并精确控制数据表示方式[^1]。 ```c struct bit_field { unsigned int flag : 1; // 占用1 unsigned int value : 7; // 占用7 }; ``` 上述代码片段展示了如何在一个`unsigned int`类型下分配不同的宽度给各个字段。值得注意的是,在某些情况下,编译器可能会根据目标平台的要求自动调整这些置或排列顺序[^4]。 #### 访问成员 一旦定义好带有的结构体之后,就可以像处理常规结构体那样对其进行初始化、读取或者修改其中的数据了: ```c struct bit_field example; example.flag = 1; // 设置标志为真 (即 '1') example.value = 59; // 给value赋值不超过其最大范围内的数值 printf("Flag=%u Value=%u\n", example.flag, example.value); ``` 这段程序说明了怎样创建一个名为 `bit_field` 的实例,并对其内部两个进行了简单操作。由于本质上还是属于某个基本数据类型的子集,因此对于可接受的最大最小值存在限制[^3]。 #### 编译器行为差异 当涉及到不同类型之间组合而成的复杂情况时,不同版本甚至同一款编译工具链也可能表现出不一致的行为模式。比如下面的例子就显示了一个混合字符型(`char`)和整形(`int`)作为基础类型的集合: ```c #include <stdio.h> struct mixed_bits { char a : 2; // 字符串中的两 char b : 3; // 另外三个比特来自同一个字节 int c : 1; // 整形的一跨越到下一个机器字边界上去了... }; int main() { printf("Size of struct mixed_bits is %lu bytes.\n", sizeof(struct mixed_bits)); } ``` 此段代码打印出来的结果会因具体环境而异,因为标准并没有明确规定跨过多个底层单的情况应该如何处理。所以在设计涉及多类型的应用之前应当充分考虑这一点[^2]。 #### 特殊情况下的无名 除了命名好的之外,还可以设置一些未被指派名字的空间来充当间隔作用或是为了满足特定硬件需求所必需留白的地方。这类匿名条目不会参与任何实际运算过程,仅起到占效果而已: ```c struct padding_example { short data : 8; // 实际有用的八信息 short : 6; // 这里预留六个空闲不做他用 short more_data : 2; // 接下来的两置放其他东西 }; ``` 这种做法有时可以帮助开发者更好地匹配外部接口规格或者是优化存储布局以提高性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值