内存对齐

来源:互联网 发布:python 大数据处理 编辑:程序博客网 时间:2024/05/16 17:08

        执行内存分配的操作是在操作系统内核中,但一般认为内存对齐是编译器的事。因为操作系统和编译器都有默认的对齐系数,但是可以通过编译器来进行修改。比如cl.exe可以通过

#pragma pack(n)    // n = 1, 2 , 4, 8, 16来指定对齐系数。

        需要内存对齐的原因,主要是从性能方面考虑,数据结构(尤其是栈)需要在自然边界上对齐,因为CPU访问对齐边界上的数据只需要一次内存访问,而非对齐的数据需要进行两次内存访问。

        一些RISC机器强制要求内存访问是自然对齐的:一个基本类型数据所存储的位置,必须能够被该数据的类型宽度整除;结构体或者联合体的数据成员内存对齐之后,结构体或联合体本身也要进行内存对齐,其起始地址应该能被N整除,N = min(#pragma显式指定的值, 最长的数据成员的类型宽度).

        比如在64位体系结构上,指针有8Byte宽,在自然对齐情况下,指针必须存储在能被8整除的地址上。(啰嗦一句:内存按字节编址)

        C++标准中没有字节类型,只是规定了char至少8bit。通常char类型也就是8bit即1Byte,而每个地址都能被1整除,所以char类型数据总是对齐的。

        在进行内存对齐时,编译器会加入填充,在计算结构体/联合体大小时,填充也会计算在内。

        下面是win32平台的cl.exe的对齐规则:

        1. 结构体变量的首地址是其最长基本类型成员的整数倍

        2. 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding)

        3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)

        4. 如果结构体内存在长度大于处理器位数的元素,那么就以处理器的倍数为对齐单位;否则,如果结构体内的元素的长度都小于处理器的倍数的时候,便以结构体里面最长的数据元素为对齐单位。


        带成员函数的C++ class用sizeof()计算大小会得到什么结果?试验一下就知道。

原创粉丝点击