什么是字节对齐
参考什么是字节对齐,为什么要对齐?
现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。
一般而言,Java对象不需要考虑字节对齐,JVM编译时会自动优化。(注:本文中所说的jdk版本是1.8为基础的。)
但C/C++/C#等需要考虑对象次序,避免空间浪费。在c语言中,结构体有字节对齐,c++中的类也有字节对齐。
为什么要内存对齐?
硬件平台限制,内存以字节为单位,不同硬件平台不一定支持任何内存地址的存取,一般可能以双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。提高CPU内存访问速度,一般处理器的内存存取粒度都是N的整数倍,假如访问N大小的数据,没有进行内存对齐,有可能就需要两次访问才可以读取出数据,而进行内存对齐可以一次性把数据全部读取出来,提高效率。
字节对齐三规则(原文链接):
其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:
- 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
- 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
- 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
有int double char 三个类型变量的类占多少字节?如何安排能让占字节最小?
在C++中,结构体的字节对齐方式是按照成员变量的自然对齐方式进行的。自然对齐是指变量的起始地址是它自身大小的整数倍。例如,一个int类型的变量需要4字节对齐,而一个double类型的变量需要8字节对齐。
以下是一个示例,其中使用了sizeof()函数来计算三种数据成员(int、double和char)的类字节大小:
#include <iostream>
using namespace std;
class Test {
public:
int a;
double b;
char c;
};
int main() {
cout << "Size of class Test: " << sizeof(Test) << endl;
return 0;
}
输出结果为:
Size of class Test: 24
24 = 4+4(用于对齐)+8+1+7(用于对齐)
要让Test类在字节对齐后占字节最小,可把double这最长的数据类型放最前或最后。
16 = 1 + 4 + 3(用于对齐) + 8