http://m.nowcoder.com/questions?uuid=a1f3b90249ff4666879e8f695915ed7f
在32位cpu上选择缺省对齐的情况下,有如下结构体定义:
#include "iostream" using namespace std; struct Zijie { unsigned a : 19; unsigned b : 11; unsigned c : 4; unsigned d : 29; char index; }; int main() { int t = sizeof(struct Zijie); cout << t << endl; system("pause"); return 0; }
在64位windows上运行是16
分析:
由于在32位cpu上选择缺省对齐的情况下,所以每行支持4个字节即32bit
于是a和b公用一行19+11 = 30bit还剩2bit,又因为c为4bit,无法全部占据该行,故其重新开始一行,第一行空出2bit;
对于第二行,c占据前4bit,同理由于d占据29bit, 无法全部占据该行的剩余空间,所以其处于第三行,第二行中剩余28bit空出;
同理可分析第三行和第四行的空间,由于第四行占据1个直接,为了保持对其需要把剩余空间补齐
综上该结构体的大小为4*4个字节 = 16
对于这道题,首先需要知道位域的概念。
位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
位域的定义和位域变量的说明位域定义
与结构定义相仿,其形式为:
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
位域表示法
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,
允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
段将从新的存储单元开始,其偏移量为其类型大小的整数倍;(经测试此条好像仅限于char型,整型可以跨域存储)
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
段将从新的存储单元开始,其偏移量为其类型大小的整数倍;(经测试此条好像仅限于char型,整型可以跨域存储)
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。