结构体的内存对齐问题

来源:互联网 发布:手机旋律合成软件 编辑:程序博客网 时间:2024/06/05 23:41

在c、c++笔试中,内存对齐问题经常考,尽管这样,这几年来我一直忽略了这个问题,记忆中一直是大学课本中struct与union的区别,那时候也不曾有提及过内存对齐,现在想起来,真是非常大的漏洞。而且很多笔试想当然的觉得struct的大小就是内部所有变量大小的和,却不知这种错误的答案让多少面试官默默的鄙视,直到前一次面试,面试官讽刺到:“作为一个c++程序员,竟然不知道内存对齐这样的基础知识。。。”,深感愧疚,我对不起这些年与c++的朝夕相处啊!回来后查了一些文章,又做了几个测试,才搞明白其中的原理,现记录一下,方便有同样经历的猿类自查。

现举个例子:

typedef struct{       char a;       int b;       }node;cout<<sizeof(node)<<endl;


以前, 我一直以为输出的结果是5(1 + 4)  直到。。。今天它怎么变成了8!!!

分析一下,经过网上查找资料,两个原因:

1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

 

原则:

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。

对齐步骤:
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
3、结合1、2颗推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。
备注:数组成员按长度按数组类型长度计算,如char t[9],在第1步中数据自身长度按1算,累加结构体时长度为9;第2步中,找最大数据长度时,如果结构体T有复杂类型成员A的,该A成员的长度为该复杂类型成员A的最大成员长度。

废话说了这么多,我觉得还是使用言简意赅的画图诠释一下。

结构体 node

anullnullnullbbbb

 

意思是char占了4个字节,第一个字节内存值,后面三个没有用到,int使用了四个字节

再看一个例子

typedef struct{          char a;          short b;          int c;          char d;           }node;cout<<sizeof(node)<<endl;


 

输出的结果应该是12,不是8,用表格的形式表示一下,如下:

abbnullccccdnullnullnull

我觉得规律是,结构体的大小一定是内部最大类型大小的整数倍,因为边界以最大类型大小确定的。

 

以后不会再在这里翻船了!铭记!
0 0
原创粉丝点击