您的位置:首页 > 编程语言 > C语言/C++

c++中的内存字节对齐

2017-06-30 14:30 393 查看
最近游戏项目开发中遇到一件麻烦事,客户端unity开发用的C#,但需要调用C++中的函数进行消息加密,调用DLL中的接口时,C#中的结构体需要传入到C++中进行操作,但是由于C#中的消息头定义的比较苟且,没有提供一个跟C++中一一对应的结构体,导致加密后再解密出错,最后发现是内存字节对齐的问题,在C++消息头定义处加入

#pragma pack(push, 1)

#pragma pack(pop)

即可,这里顺便总结下字节对齐。

1. 基本概念
字节对齐:计算机存储系统中以Byte为单位存储数据,不同数据类型所占的空间不同,如:整型(int)数据占4个字节,字符型(char)数据占一个字节,短整型(short)数据占两个字节,等等。计算机为了快速的读写数据,默认情况下将数据存放在某个地址的起始位置,如:整型数据(int)默认存储在地址能被4整除的起始位置,字符型数据(char)可以存放在任何地址位置(被1整除),短整型(short)数据存储在地址能被2整除的起始位置。这就是默认字节对齐方式

2.数据成员对齐规则

结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储

3. 举例说明

很显然默认对齐方式会浪费很多空间,例如如下结构:

struct student

{

    char name[5];

    int num;

    short score;

}

本来只用了11bytes(5+4+2)的空间,但是由于int型默认4字节对齐,存放在地址能被4整除的起始位置,即:如果name[5]从0开始存放,它占5bytes,而num则从第8(偏移量)个字节开始存放。所以sizeof(student)=16。于是中间空出几个字节闲置着。但这样便于计算机快速读写数据,是一种以空间换取时间的方式。其数据对齐如下图:
|char|char|char|char|

|char|----|----|----|

|--------int--------|

|--short--|----|----|

4. #pragma pack()命令

为了节省空间,我们可以在编码时通过#pragma pack()命令指定程序的对齐方式,括号中是对齐的字节数,若该命令括号中的内容为空,则为默认对齐方式。例如,对于上面第一个结构体,如果通过该命令手动设置对齐字节数如下:
#pragma pack(push,2) //设置2字节对齐

struct strdent

{

    char name[5]; //本身1字节对齐,比2字节对齐小,按1字节对齐

    int num;          //本身4字节对齐,比2字节对齐大,按2字节对齐

    short score;    //本身也2字节对齐,仍然按2字节对齐

}

#pragma pack() //取消设置的字节对齐方式
则,num从第6(偏移量)个字节开始存放,score从第10(偏移量)个字节开始存放,故sizeof(student)=12
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: