目录
一、内存对齐原则的意义
简单来说,就是方便计算机去读写数据。
对齐的地址一般都是 n(n = 2、4、8)的倍数。
(1). 1 个字节的变量,例如 char 类型的变量,放在任意地址的位置上;
(2). 2 个字节的变量,例如 short 类型的变量,放在 2 的整数倍的地址上;
(3). 4 个字节的变量,例如 float、int 类型的变量,放在 4 的整数倍地址上;
(4). 8 个字节的变量,例如 long long、double 类型的变量,放在 8 的整数倍地址上;
二、基本变量类型所占大小
| 数据类型 | ILP32(32位Linux系统) | LP64(大部分64位Linux系统) | LLP64(64位Windows系统) |
| int | 4字节 | 4字节 | 4字节 |
| float | 4字节 | 4字节 | 4字节 |
| char | 1字节 | 1字节 | 1字节 |
| short | 2字节 | 2字节 | 2字节 |
| double | 8字节 | 8字节 | 8字节 |
| long | 4字节 | 8字节 | 4字节 |
| longlong | 8字节 | 8字节 | 8字节 |
| point(指针) | 4字节 | 8字节 | 8字节 |
| enum(枚举) | 4字节 | 4字节 | 4字节 |
注:
ILP32 指 int,long、point 是 32 位。
LP64 指 long、point 是 64 位。
LLP64 指 long long、point 是 64 位。
三、影响内存对齐的情况
1、变量排列顺序
2、attribute((packed)):取消变量对齐,按照实际占用字节数对齐(就是让变量之间排列紧密,不留缝隙)。(gcc才支持)详见例7。
3、#pragma pack (n):让变量强制按照 n 的倍数进行对齐,并会影响到结构体结尾地址的补齐(详见四的通常情况下关于结尾地址补齐的描述)。
四、系统默认遵循内存对齐原则的操作
下面的结论均为系统默认对齐规则下进行的:
通常情况:
结构体中间:各结构体的起始地址按照各个类型变量默认规则进行摆放,但除了 char 类型变量(详见一),char 类型变量一般遵循 2 的倍数地址开始存储。
结构体最后(重要):视结构体中最大类型是哪一个,如果是像 int 类型那样是 4 个字节的,并且结构体的结尾地址不满足 4 的倍数的话,向离最近的 4 的倍数地址补齐;如果是像 double 类型那样是 8 个字节的,并且结构体的结尾地址不满足 8 的倍数的话,向离最近的 8 的倍数地址补齐;以此类推。
结构体嵌套:子结构体的成员变量起始地址要视子结构体中最大变量类型决定,比如 struct a 含有 struct b,b 里有 char,int,double 等元素,那 b 应该从 8 的整数倍开始存储。
含数组成员:比如 char a[5],它的对齐方式和连续写 5 个 char 类型变量是一样的,也就是说它还是按一个字节对齐。
含联合体(union)成员:取联合体中最大类型的整数倍地址开始存储。
五、例子
以下是一个遵循结构体内存对齐原则的代码实现:
#include <stdio.h>
// 定义一个结构体,包含不同类型的成员
struct MyStruct {
char c; // 1字节
int i; // 4字节
short s; // 2字节
double d; // 8字节
};
int main() {
// 计算结构体的大小
printf("Size of MyStruct: %zu bytes\n", sizeof(struct MyStruct));
// 创建结构体变量
struct MyStruct myStruct;
// 访问结构体成员
myStruct.c = 'A';
myStruct.i = 12345;
myStruct.s = 678;
myStruct.d = 3.14159265359;
// 打印结构体成员的值
printf("c: %c\n", myStruct.c);
printf("i: %d\n", myStruct.i);
printf("s: %hd\n", myStruct.s);
printf("d: %lf\n", myStruct.d);
return 0;
}
//在这个例子中,我们定义了一个结构体 MyStruct,它包含了不同类型的成员:char、int、short 和 double。为了遵循内存对齐原则,结构体的大小应该是其最大成员大小的整数倍。在这个例子中,double 是最大的成员,占用 8 字节,因此结构体的大小应该是 8 的整数倍。
在这个例子中,我们定义了一个结构体 MyStruct,它包含了不同类型的成员:char、int、short 和 double。为了遵循内存对齐原则,结构体的大小应该是其最大成员大小的整数倍。在这个例子中,double 是最大的成员,占用 8 字节,因此结构体的大小应该是 8 的整数倍。


1706

被折叠的 条评论
为什么被折叠?



