IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C/C++】内存对齐(超详细,看这一篇就够了) -> 正文阅读

[C++知识库]【C/C++】内存对齐(超详细,看这一篇就够了)

目录

一、为什么要内存对齐

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

三、影响内存对齐的情况

四、先说结论(重要)

五、举亿点例子(以下内容均实际运行过,质量保证)

?例1:研究结构体最后一个成员内存对齐问题1

?例2:研究结构体最后一个成员内存对齐问题2

?例3: 研究数组的内存对齐

例4:枚举 & 研究数组之间的内存对齐

例5:结构体嵌套1

例6:结构体嵌套2

例7:__attribute__((packed))?

例8:#pragma pack (n)

? ? ? ? 写在前面:本次实验所用到的环境:Windows 10 Visual Studio(64 位)、Ubuntu 18.04 x86_64-linux-gnu(64 位)!!

一、为什么要内存对齐

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

? ? ? ? 对齐的地址一般都是 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系统)
char1 字节1 字节1 字节
short2 字节2 字节2 字节
int4 字节4 字节4 字节
float4 字节4 字节4 字节
long4 字节8 字节4 字节
double8 字节8 字节8 字节
long long8 字节8 字节8 字节
指针 point4 字节8 字节8 字节
枚举 enum4 字节4 字节4 字节
联合体? union取 union 中最大一个变量类型大小取 union 中最大一个变量类型大小取 union 中最大一个变量类型大小

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 的倍数进行对齐,并会影响到结构体结尾地址的补齐(详见四的通常情况下关于结尾地址补齐的描述)。详见例8。

四、先说结论(重要)

下面的结论均为系统默认对齐规则下进行的:

通常情况:我总结的规律如下:结构体中间:各结构体的起始地址按照各个类型变量默认规则进行摆放,但除了 char 类型变量(详见一),char 类型变量一般遵循 2 的倍数地址开始存储。详见例2。结构体最后(重要)视结构体中最大类型是哪一个,如果是像 int 类型那样是 4 个字节的,并且结构体的结尾地址不满足 4 的倍数的话,向离最近的 4 的倍数地址补齐;如果是像 double 类型那样是 8 个字节的,并且结构体的结尾地址不满足 8 的倍数的话,向离最近的 8 的倍数地址补齐;以此类推。。。。

结构体嵌套:子结构体的成员变量起始地址要视子结构体中最大变量类型决定,比如 struct a 含有 struct b,b 里有 char,int,double 等元素,那 b 应该从 8 的整数倍开始存储。详见例5、例6。

含数组成员:比如 char a[5],它的对齐方式和连续写 5?个 char 类型变量是一样的,也就是说它还是按一个字节对齐。详见例1、例2、例3、例4、例5。

含联合体(union)成员:取联合体中最大类型的整数倍地址开始存储。详见例5。

个人总结能力有限,还是观看例子更容易理解:

五、举亿点例子(以下内容均实际运行过,质量保证)

没有特别标注就是 64 位!!

?例1:研究结构体最后一个成员内存对齐问题1

struct stu1 {
    char a[18];
    double b;
    char c;
    int d;
    short e;
};

?Windows 10:48 字节????????????????????????Ubuntu 18.04:48 字节

?例2:研究结构体最后一个成员内存对齐问题2

struct stu1 {
    char a[18];
    int b[3];
    short c;
    char d;
    int e;
    short f;
};

?Windows 10:44 字节????????????????????????Ubuntu 18.04:44 字节

?

?例3: 研究数组的内存对齐

struct stu1 {
    int a;
    char b[8];
    float c;
    short d;
};

?Windows 10:20 字节????????????????????????Ubuntu 18.04:20 字节?

?

例4:枚举 & 研究数组之间的内存对齐

enum DAY {
    MON = 1, TUE, WED, THU, FRI, SAT, SUN
};
struct stu1 {
    char a[5];
    char b[3];
    enum DAY day;
    int *c;
    short d;
    int e;
};

??Windows 10:32 字节? ? ? ? Windows 10(32位):24 字节?? ? ? ?Ubuntu 18.04:32 字节?

64位:

32位:?

?

例5:结构体嵌套1

struct stu2 {
    char x;
    int y;
    double z;
    char v[6];
};
struct stu1 {
    union u1 {
        int a1;
        char a2[5];
    }a;
    struct stu2 b;
    int c;
};

??Windows 10:40 字节????????????????????????Ubuntu 18.04:40 字节

?

例6:结构体嵌套2

struct stu2 {
    char x;
    int y;
    double z;
    char v[6];
};
struct stu1 {
    char a;
    struct stu2 b;
    int c;
};

???Windows 10:40 字节????????????????????????Ubuntu 18.04:40 字节

?

例7:__attribute__((packed))?

由于 VS 和 VScode?均不支持 __attribute__((packed))?,于是只使用 gcc 编译。

struct __attribute__((packed)) stu1 {    // 取消内存对齐
    char a;
    long b;
    short c;
    float d;
    int e;
};

Ubuntu 18.04:16 字节

?

例8:#pragma pack (n)

#pragma pack (2)    // 强制以 2 的倍数进行对齐
struct stu1 {
    short a;
    int b;
    long c;
    char d;
};
#pragma pack ()    // 取消强制对齐,恢复系统默认对齐

???Windows 10:12 字节????????????????????????Ubuntu 18.04:16 字节

正常情况:?

Windows 10:

?Ubuntu 18.04:

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 20:56:54  更:2022-10-22 20:58:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 5:21:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码