应用场景
数据仅需要0和1表示,例如:开关通电和断电两种状态,用 0 和 1 表示,用一个二进位。
位域实例
结构体定义
struct bs{
unsigned int m;
unsigned int n: 4;
unsigned char ch: 6;
};
m:占用 4 个字节(Byte)的内存;
n:“:”后面的数字限定n占用的位数,不能再根据数据类型计算长度,n占用4位(Bit)内存;
ch:占用6位(Bit)内存。
#include <stdio.h>
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值 0xE,二进制 1110、ch 值0x24('$' ASCII 码 0x24)二进制10 0100,不超出限定位数,能正常输出。
第二次输出:n值0x2d,二进制10 1101、ch 值0x7a('z' ASCII 码为0x7a),二进制111 1010,都超出限定的位数,仅留下未超出部分 1101、11 1010,十六进制为:0xd、0x3a(0x3a 对应的字符是 :)。
C语言标准规定
1)位域的宽度不能超过它所依附的数据类型的长度。通俗地讲,成员变量都是有类型的,这个类型限制了成员变量的最大长度,“:”后面的数字不能超过这个长度。
2)只有有限的几种数据类型可以用于位域。在 ANSI C 中,这几种数据类型是 int、signed int 和 unsigned int(int 默认就是 signed int);到了 C99,_Bool 也被支持了。
3)编译器在具体实现时都进行了扩展,额外支持了 char、signed char、unsigned char 以及 enum 类型,所以上面的代码虽然不符合C语言标准,但它依然能够被编译器支持。