C++内存对齐笔记

来源:互联网 发布:手机淘宝店如何招代理 编辑:程序博客网 时间:2024/06/05 11:47

Win8.1 64 Visual Studio 2013 Community 环境

内存对齐能够使CPU高效地从内存中进行数据读写,提高程序的运行效率。

何为内存对齐

内存对齐指数据存放的内存地址是否为对齐字节大小的倍数(一般为2的幂)。
实际上,C++中的基本数据类型默认的对齐字节为该数据类型的大小
如:char为1,short为2,int为4,float为4,double为8。

对象内存分布

struct和class中成员变量的内存对齐十分重要。如下代码:

struct X{    char a;    int b;    char c;};struct Y{    int a;    char b;    char c;};int main(){    cout << sizeof(X) << endl;    cout << sizeof(Y) << endl;    system("pause");    return 0;}

X,Y结构的成员大小都是6(4+1+1),但是输出结果却分别是12和8。其他造成不同的原因就是内存对齐。C++规定,对象的第一个成员的内存地址偏移量为0
对于X:
a为char,占据内存的 0。
b为int,根据内存对齐,int的对齐字节为4,就是地址偏移必须为4的倍数,所以不能从地址1,2,3 开始放,只能放在[4,7]位。
c为char,放在 8 位。
总共是9位,对于整个结构体 X来说,也必须要内存对齐。对齐为成员中最大的字节4(int b),所以在末尾填充3个字节(padding),共计为12(4的倍数)。编译器加上这种填充,是为了当存在一个结构体数组时,仍能够正确的对齐,即只要定义此结构体的数组,并首个元素对齐,则整个数组元素都是对齐的
对于Y:
a为int ,占据[0,3]。
b为char,占据4
c为char ,占据5
总计6位,Y的对齐字节为4(int),所以自动填充两位变成8,构成4的倍数。

pragma pack(n)指令

使用#pragma pack(n)指令,可以改变对齐字节数。规定如下:

除了第一个成员变量,其余变量的内存地址偏移为min(n,sizeof(当前变量类型))。

整个结构的最终大小,必须是min(n,sizeof(最大变量类型))的倍数。

n为2的幂

从下面几个例子解释该命令:
首先没有#pragma pack命令

struct X{    char a;    double b;    short c;};

a为char,内存 0。
b为double,首地址必须在8的倍数,即[8,15]。
c为short,首地址2的倍数,即[16,17]。
共18位,结构大小必须是最大对齐字节倍数(8),即24。
输出大小为24。

使用#pragma pack(n)命令

#pragma pack(4)struct X{    char a;    double b;    short c;};

a为char,内存地址 0
b为double min(4,sizeof(double))=4 从4开始,[4,11]
c为short min=2,从12开始,[12,13]
最终大小14,min(4,8)=4,需要4的倍数,所以为16
输出大小为16。

#pragma pack(2)struct X{    char a;    double b;    short c;};

a 0
b min(2,8)=2, [2,9]
c min=2, [10 11]
共12字节,为min(2,8)=2的倍数,所以最终大小为12。

__declspec(align(m))指令

__declspec(align(m)) 确定整个结构的对齐字节,即调整整个结构的最终大小。

结构的最终大小,必须为max(m,sizeof(最大成员类型))的倍数。

m为2的幂

struct X{    short a;    double b;    int c;};

a [0,1]
b [8,15]
c [16 19]
共20字节,必须为8的倍数,所以最终为24字节

 __declspec(align(16))struct X{    short a;    double b;    int c;};

同上,共20字节,max(16,8)=16,必须为16的倍数,所以最终大小为32字节。

__declspec(align(m))和#pragma pack(n)

两者同时出现时,由于__declspec(align(m))优先级较高,所以最终的结构大小按照 __declspec(align(m))的方式决定。

#pragma pack(2) __declspec(align(16))struct X{    short a;    double b;    int c;};

a [0,1]
b min(2,8)=2,[2,9]
c min=2, [10,13]
共14字节,结构大小需要为max(16,8)=16的倍数,所以为16

成员变量为结构体

__declspec(align())优先级高于#pragma pack

受__declspec(align())影响的结构体成员变量的对齐字节,由其__declspec(align())决定,不受#pragma pack影响

#pragma pack(push ,2) //所有结构体都受pack作用 __declspec(align(32))struct X{    char a;    int b;    double c;};__declspec(align(64))struct Y{    int a;    double b;    X c;    int d;};int main(){    X x;    Y y;    cout << hex;    cout << (long)&x.a << endl;    cout << (long)&x.b << endl;    cout << (long)&x.c << endl;    cout << endl;    cout << (long)&y.a << endl;    cout << (long)&y.b << endl;    cout << (long)&y.c << endl;    cout << (long)&y.d << endl;    cout << endl;    cout << dec;    cout << sizeof(X) << endl;    cout << sizeof(Y) << endl;    system("pause");    return 0;}

对于X
a 0
b min=2, [2,5]
c min=2, [6,13]
共14,max(8,32)=32,最终大小为32

对于Y
a [0,3]
b min=2, [4,11]

c 受__declspec(align(32))影响的结构体,

由于__declspec的优先级高,所以c必须为32位对齐(不受pack影响)

所以c最终为[32,63]

d min=2 ,[64,67]
共68字节,由于Y受__declspec(align(64)) 影响,必须为max(64,32)=64的倍数,最终大小为128字节。

0 0
原创粉丝点击