C++常见面试问题之内存对齐

一、内存对齐是什么

1.内存对齐是什么

还是用一个例子带出这个问题,看下面的小程序,理论上,32位系统下,int占4byte,char占一个byte,那么将它们放到一个结构体中应该占4+1=5byte;但是实际上,通过运行程序得到的结果是8 byte,这就是内存对齐所导致的。

复制代码
//32位系统
#include<stdio.h>
struct{
    int x;
    char y;
}s;

int main()
{
    printf("%d\n",sizeof(s);  // 输出8
    return 0;
}

现代计算机中内存空间都是按照 byte 划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐。

2.内存对齐规则

那么接下来我们来说一下结构体中内存对齐的规则:

1.对于结构体中的各个成员,第一个成员位于偏移为 0 的位置,以后的每个数据成员的偏移量必须是min(#pragma pack()制定的数,数据成员本身长度)的倍数。 n= 1,2,4,8,16

每个特定平台上的编译器都有自己的默认"对齐系数"(也叫对齐模数)。gcc中默认#pragma pack(4),可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变这一系数。

2.在所有的数据成员完成各自对齐之后,结构体或联合体本身也要进行对齐,整体长度是 min(#pragma pack())制定的数,长度最长的数据成员的长度)的倍数

二、为什么内存对齐

内存对齐的作用:

1.经过内存对齐之后,CPU 的内存访问速度大大提升 。因为 CPU 把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此 CPU 在读取内存的时候是一块一块进行读取的,块的大小称为内存读取粒度。比如说CPU 要读取一个 4 个字节的数据到寄存器中(假设内存读取粒度是 4),如果数据是从0字节开始的,那么直接将0-3 四个字节完全读取到寄存器中进行处理即可。

2.如果数据是从1字节开始的,就首先要将前 4 个字节读取到寄存器,并再次读取 4-7 个字节数据进入寄存器,接着把0字节,5,6,7字节的数据剔除,最后合并 1,2,3,4 字节的数据进入寄存器,所以说,当内存没有对齐时,寄存器进行了很多额外的操作,大大降低了 CPU 的性能 。 3.另外,还有一个就是,有的 CPU 遇到未进行内存对齐的处理直接拒绝处理,不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。所以内存齐还有利于平台移植。

相关推荐
悠仁さん3 分钟前
【C++】set map 使用
java·前端·c++
艾莉丝努力练剑14 分钟前
【AI大模型接入SDK】ChatServer问题修复
c++·学习·ai·大模型·sdk
扶尔魔ocy1 小时前
【QT C++】常用设计模式
c++·设计模式
晚风予卿云月1 小时前
【C++高并发内存池】 2.ThreadCache设计
开发语言·c++·高并发内存池·tcmalloc
Dovis(誓平步青云)1 小时前
拖动关键帧角色就抽动,动画编辑器怎样补齐中间状态
开发语言·前端·javascript·机器学习·编辑器
行走的陀螺仪2 小时前
Claude Code 从入门到实战(二):Bash工具、Plan模式与后台任务
开发语言·bash
東隅已逝,桑榆非晚2 小时前
红黑树:从概念到实现
数据结构·c++·笔记·学习
努力努力再努力wz2 小时前
【Lua 入门系列】从执行模型到事件驱动:一文理解 Lua 有栈协程、挂起恢复与协作式调度
开发语言·lua
椒颜皮皮虾྅2 小时前
一套 C# 接口,解锁四类视觉任务:DeploySharp 分类、分割、关键点与旋转框实战
开发语言·分类·c#
2603_965896622 小时前
JavaScript 原型与原型链
开发语言·前端·javascript