C/C++中的内存对齐原则

目录

一、内存对齐原则的意义

二、基本变量所占类型的大小

三、影响内存对齐的情况

四、系统默认遵循内存对齐原则的操作

五、例子


  一、内存对齐原则的意义

         

      简单来说,就是方便计算机去读写数据。

   对齐的地址一般都是 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系统)
int4字节4字节4字节
float4字节4字节4字节
char1字节1字节1字节
short2字节2字节2字节
double8字节8字节8字节
long4字节8字节4字节
longlong8字节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 的整数倍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值