位域实践
有如下代码:
1: #include <stdio.h>
2:
3: #include <string.h>
4:
5: #include <malloc.h>
6:
7: #include <stdlib.h>
8:
9: typedef struct AA
10:
11: {
12:
13: int b1:5;
14:
15: int b2:2;
16:
17: }AA;
18:
19: int main(){
20:
21: AA aa;
22:
23: char cc[100];
24:
25: strcpy_s(cc,"0123456789abcdefghijklmnopqrstuvwxyz\0");
26:
27: printf("%d\n",sizeof(cc));
28:
29: printf(" %d \n",sizeof(AA));
30:
31: memcpy(&aa,cc,sizeof(AA));
32:
33: printf("aa.b1 = %d\n",aa.b1);
34:
35: printf("aa.b2 = %d\n",aa.b2);
36:
37: system("pause");
38:
39: }
运行结果:
当时对这个结果非常的费解,memcpy(&aa,cc,sizeof(AA)); 将会从数组cc中拷贝4个字节到结构体aa中,拷贝过后的结果如下图所示,其中的0x30、0x31、0x32、0x33分别是"0123"的
码(注意:字符在内存中是按照ASCII值存放的)。
由于intel是Little endian(小高高),小端格式+高位存放在高地址,所以b1和b2一起占据了第一个字节的前七位,由于第一字节0x30=0011 0000,所以b1=1 0000,b2=01,由于在输出的时候要进行符号位的扩展,所以b1=0xffff fff0=-16,b2=0x0000 0001=1,这就是上面的输出结果。
下面的截图来自:C: in a nutshell
其实我们可能不希望由于符号位的扩展而导致正数变成负数,这就需要将位域的类型定义为unsigned int,如下所示:
这样输出结果就是16和1了,如下图所示:
位域的大小
上面结构的大小是4.
上面结构的大小是1.
以上结果都是在VS2008中得到的。
空位域:
定义为unsigned int :0,表示从下一个边界开始存放。
Sizeof(AA)为:16
如果不用空位域,着sizeof(AA)为12,如下图所示:
注意:每一个位域的大小不能够超过了其自身类型的大小,如下面的定义是错误的:
参考资料: