千家信息网

C言语位域

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,有些数据在存储时并不需求占用一个完好的字节,只需求占用一个或几个二进制位即可。例如开关只要通电和断电两种形态,用 0 和 1 表现足以,也就是用一个二进位。恰是基于这种思索,C言语又供给了一种叫做位域
千家信息网最后更新 2026年11月01日C言语位域

有些数据在存储时并不需求占用一个完好的字节,只需求占用一个或几个二进制位即可。例如开关只要通电和断电两种形态,用 0 和 1 表现足以,也就是用一个二进位。恰是基于这种思索,C言语又供给了一种叫做位域的数据构造。
在构造体界说时,我们可以指定某个成员变量所占用的二进制位数(Bit),这就是位域。请看下面的例子:

                 struct bs{ unsigned m; unsigned n: 4; unsigned char ch: 6; }

:前面的数字用来限制成员变量占用的位数。成员 m 没无限制,依据数据类型即可推算出它占用 4 个字节(Byte)的内存。成员 n、ch 被:前面的数字限制,不克不及再依据数据类型盘算长度,它们辨别占用 4、6 位(Bit)的内存。
n、ch 的取值规模十分无限,数据略微大些就会发作溢出,请看下面的例子:

                  #include  int main(){ struct bs{ unsigned m; unsigned n: 4; unsigned char ch: 6; } a = { 0xad, 0xE, '$'}; //第一次输入 printf("%#x, %#x, %c\n", a.m, a.n, a.ch); //更改值后再次输入 a.m = 0xb8901c; a.n = 0x2d; a.ch = 'z'; printf("%#x, %#x, %c\n", a.m, a.n, a.ch); return 0; }

运转后果:
0xad, 0xe, $
0xb8901c, 0xd, :
关于 n 和 ch,第一次输入的数据是完好的,第二次输入的数据是完整的。
第一次输入时,n、ch 的值辨别是 0xE、0x24('$' 对应的 ASCII 码为 0x24),换算成二进制是 1110、10 0100,都没有超越限制的位数,可以正常输入。
第二次输入时,n、ch 的值变为 0x2d、0x7a('z' 对应的 ASCII 码为 0x7a),换算成二进制辨别是 10 1101、111 1010,都超越了限制的位数。超越局部被直接截去,剩下 1101、11 1010,换算成十六进制为 0xd、0x3a(0x3a 对应的字符是 :)。
C言语规范规则,位域的宽度不克不及超越它所依靠的数据类型的长度。浅显地讲,成员变量多是有类型的,这个类型限制了成员变量的最大长度,:前面的数字不克不及超越这个长度。
例如下面的 bs,n 的类型是 unsigned int,长度为 4 个字节,合计 32 位,那么 n 前面的数字就不克不及超越 32;ch 的类型是 unsigned char,长度为 1 个字节,合计 8 位,那么 ch 前面的数字就不克不及超越 8。
我们可以如许以为,位域技巧就是在成员变量所占用的内存当选出一局部位宽来存储数据。
C言语规范还规则,只要无限的几种数据类型可以用于位域。在 ANSI C 中,这几种数据类型是 int、signed int 和 unsigned int(int 默许就是 signed int);到了 C99,_Bool 也被支撑了。

关于C言语规范以及 ANSI C 和 C99 的差别,我们已在VIP教程《C言语的两套规范》中停止了解说。

但编译器在详细完成时都停止了扩大,额定支撑了 char、signed char、unsigned char 以及 enum 类型,所以下面的代码固然不契合C言语规范,但它仍然可以被编译器支撑。

位域的存储

C言语规范并没有规则位域的详细存储方法,分歧的编译器有分歧的完成,但它们都尽量紧缩存储空间。
位域的详细存储规矩如下:
1) 当相邻成员的类型相反时,假如它们的位宽之和小于类型的 sizeof 巨细,那么前面的成员紧邻前一个成员存储,直到不克不及包容为止;假如它们的位宽之和大于类型的 sizeof 巨细,那么前面的成员将重新的存储单位开端,其偏移量为类型巨细的整数倍。
以下面的位域 bs 为例:

                  #include  int main(){ struct bs{ unsigned m: 6; unsigned n: 12; unsigned p: 4; }; printf("%d\n", sizeof(struct bs)); return 0; }

运转后果:
4
m、n、p 的类型多是 unsigned int,sizeof 的后果为 4 个字节(Byte),也即 32 个位(Bit)。m、n、p 的位宽之和为 6+12+4 = 22,小于 32,所以它们会挨着存储,两头没有裂缝。

sizeof(struct bs) 的巨细之所认为 4,而不是 3,是由于要将内存对齐到 4 个字节,以便进步存取效力,这将在《C言语和内存》专题的《C言语内存对齐,进步寻址效力》一节中具体解说。

假如将成员 m 的位宽改为 22,那么输入后果将会是 8,由于 22+12 = 34,大于 32,n 会重新的地位开端存储,绝对 m 的偏移量是 sizeof(unsigned int),也即 4 个字节。
假如再将成员 p 的位宽也改为 22,那么输入后果将会是 12,三个成员都不会挨着存储。
2) 当相邻成员的类型分歧时,分歧的编译器有分歧的完成计划,GCC 会紧缩存储,而 VC/VS 不会。
请看下面的位域 bs:

                 #include  int main(){ struct bs{ unsigned m: 12; unsigned char ch: 4; unsigned p: 4; }; printf("%d\n", sizeof(struct bs)); return 0; }

在 GCC 下的运转后果为 4,三个成员挨着存储;在 VC/VS 下的运转后果为 12,三个成员依照各自的类型存储(与不指定位宽时的存储方法相反)。

m 、ch、p 的长度辨别是 4、1、4 个字节,合计占用 9 个字节内存,为什么在 VC/VS 下的输入后果倒是 12 呢?这个疑问将在《C言语和内存》专题的《C言语内存对齐,进步寻址效力》一节中为您解开。

3) 假如成员之间交叉着非位域成员,那么不会停止紧缩。例如关于下面的 bs:

                       struct bs{ unsigned m: 12; unsigned ch; unsigned p: 4; };

在各个编译器下 sizeof 的后果多是 12。
经过下面的剖析,我们发现位域成员常常不占用完好的字节,有时分也不处于字节的扫尾地位,因而运用&获取位域成员的地址是没有意义的,C言语也制止如许做。地址是字节(Byte)的编号,而不是位(Bit)的编号。

无名位域

位域成员可以没著名称,只给出数据类型和位宽,如下所示:

                    struct bs{ int m: 12; int : 20; //该位域成员不克不及运用 int n: 4; };

无名位域普通用来作填充或许调剂成员地位。由于没著名称,无名位域不克不及运用。
下面的例子中,假如没有位宽为 20 的无名成员,m、n 将会挨着存储,sizeof(struct bs) 的后果为 4;有了这 20 位作为填充,m、n 将离开存储,sizeof(struct bs) 的后果为 8。


成员 类型 存储 言语 字节 数据 后果 输入 内存 面的 长度 分歧 变量 数字 编译器 编译 限制 二进制 位数 巨细 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司 广州为想互联网科技有限公司 山东特亿宝互联网科技有限公司 关于新基建和互联网科技 易互联网科技有限公司 互联网 科技创新 沃里互联网科技 融贸通互联网科技 互联网科技公司有哪些 恒生科技互联网指数分析 成都玖崟互联网科技有限公司乐商圈怎么样 互联网科技实习生岗位职责 中化能源互联网科技招聘 银川新华互联网科技学校联系电话 华夏恒生科技与互联网科技 卓翼科技产业互联网合作 长沙互联网科技 互联网风格科技公司名称 求路客互联网科技电话 如何强化互联网金融科技 中智农互联网科技 科技股互联网 博兴的互联网电子科技公司 互联网还是高科技吗 互联网科技革命什么开始 互联网媒体平台算高科技产业 洛阳共同富裕互联网科技有限公司 宁波跨境商互联网科技有限公司 昆明中奇联合互联网科技 杭州融税互联网科技有限公司
0