从网上看到这样一段c代码,让我发觉我的C基本功还是不行啊~~
- typedef struct xp {
- int a:2;
- int b:2;
- unsigned int c:1;
- } xp;
不知道大家对int声明中的这个":"熟悉吗?不过,我刚看到的时候有点懵。在网上查了些资料,才明白这是一种将int按位分配的方法。
比如:int a:2;表示a为占2位的整数。
通常的int为4字节,即占用32位的整数。
同时 按位分配的int,也分有符号和无符号两种,如:
- typedef xp
- {
- int a:2;
- unsigned int b:2;
- }MyXp;
- MyXp x;
- x.a = 3;
- x.b = 3;
这样,输出的x.a为-1,x.b为3。
同时,大家看到,这种分配方法是定义在struct中的。如果你在代码中直接定义:int a:2;编译时会导致错误,无法识别“:”。
这是因为int是内建类型,它不能被改变内存分配的方式。所以单独的int,不能直接被声明为只占2位。
而在struct中,对整个struct的内存分配,还是遵循c的内存分配方式,但在其中每一个内存位的表示含义,则可以由我们自己说明。如下:
- printf("%d/n", sizeof(x));
- printf("%d/n",sizeof(x.a));
第一句能返回4,表示MyXp是占用4个字节的,其实其中的多个int,对系统来说只是将一个int截成了不同的段来使用,整个内存分配还是按照一个int来。当然,如果总位数超过了32位,那struct大小会以4字节为单位递增,即struct的大小为4字节、8字节、12字节等。
而同时,第二句printf编译错误,是因为系统识别不出x.a的类型,因为他不是普通的int类型,系统无法识别x.a占用了2位。
从内存上看,a和b占用了x的32位中的低4位,高位没有分配的会以0值填充。
有兴趣的可以看一下运行时的内存分配。struct中的a、b是公用一个int的内存段,如果再添加新的变量,他们也是使用同一个int内存段,直到一个int段不够,则直接再开一个int段供使用。同时,如果反编译这段代码,也能发现,对a、b的赋值和访问和一般的int不同,是通过位操作来进行的。
注意,共享内存段的只能是在struct中连续声明的按位分配的int变量,如下声明:
- typedef struct xp {
- int a:3;
- int b:2;
- int k;
- unsigned int c:2;
- } xp;
则xp会占用3个int的内存段,因为a、b共享一个int的4字节,k自己单独占用一个int,c则需要开一个新的int内存段使用。而如果将k和c的声明互换,则xp只需要占用2个int的内存段。