C语言的内存对齐
从一个例子开始
象下面这样定义的结构体占几个字节?
typedef struct{
char a;
int i;
} Sample;
char占1个字节,int占4个字节,答案是5个字节? 错了。如果用 gcc 编译,sizeof(Sample) 的结果是8个字节。
这是怎么回事?进一步观察,Sample第0个字节是a, 而Sample的成员int i从第4个字节开始。 这是编译器为了内存对齐所做的优化。
什么是内存对齐
比如数据总线有32位,它访存只能4个字节4个字节地进行。 0-3,4-7,8-11,12-15,…… 即使我们需要的数据只占一个字节,也是一次读取4个字节。 一个字节的数据不管地址是什么,都能通过一次访存读取出来。 而如果要读取的数据是一个字节以上,比如两个字节, 如果该数据的内存地址是0x03,则需要两次才能读取该数据, 第一次读0x00-0x03,第二次读0x04-0x07。 这个数据就跨越了访存边界。
而相对CPU的运算来说,访存是非常慢的,所以要尽量减少访存次数。 为了减少跨越访存边界的数据引起的访存开销, 所以编译器会进行内存对齐,即把变量的地址做一些偏移, 目的是一次访存就读出数据,不然的话也要以尽可能少地访存次数读出数据。
如上一个例子中那样,整型成员i的地址做4个字节的偏移, 而Sample对象的地址也会做4字节边界的对齐, 这样i的地址始终是4的倍数,从而使得i不跨越访存边界, 能一次读出它的值。
尽可能少的内存占用
typedef struct{
char a;
char b;
int i;
} Sample1;
Sample1占多少空间呢?仍然是8个字节。 a在第0个字节,b在第1个字节,i占4-7字节。 这是内存对齐的原则,占用尽量少的内存。 如果在b之后,还有char类型的成员c和d,同样是占8个字节。 a,b,c,d在0-3字节。
数据成员顺序影响内存的占用
typedef struct{
char a;
int i;
char b;
} Sample2;
Sample2的数据成员和Sample1的数据成员相同,只是顺序不一样, 是否占用一样多的内存呢?答案是不一样。 Sample1占用8字节,而Sample2占用12个字节!
这是为什么呢?32位机器上,访存单元是4字节。 对于多于4字节的数据,以4字节为单位做内存对齐的。 所以对于上述的结构体数据的地址分配,都是4的倍数。 对于结构体内部,以数据成员的最大长度为对齐单位。 如果数据成员的长度超过4字节,仍然以4字节为对齐单位,这是因为访存单元就是4字节。 在Sample2的定义中,因为int是4字节,所以以4字节为内存对齐的单位。
在Sample2中,对于a来说,只占一个字节,无所谓对不对齐,它在0字节。 i是int类型,要对齐,在4-7字节。 b在8字节,虽然它只占一个字节,但因为结构体内是以4字节为单位对齐的, 所以编译器一下多分配出4个字节,所以共占了12个字节。
以上的Sample1和Sample2的例子说明,即使是同样的结构体,如果数据成员的顺序不同,所占的内存空间可能是不同的。
总结
如果我们对内存对齐有概念,在定义结构体的时候就会留心数据成员的顺序,从而能 减少程序的内存占用。
以前我使用变量存放较小的整数时,为了减小内存占用,往往把变量定义成char型, 但现在明白了,因为编译器的内存对齐,节省内存的效果并没有那么理想。
如果内存真的很受限,可以用 #pragma pack(1) 告诉编译器关闭内存对齐。
C语言的内存对齐的更多相关文章
- C语言中内存对齐规则讨论(struct)
C语言中内存对齐规则讨论(struct) 对齐: 现代计算机中内存空间都是按着byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地 ...
- C语言中内存对齐方式
一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...
- c语言中内存对齐问题
在最近的项目中,我们涉及到了“内存对齐”技术.对于大部分程序员来说,“内存对齐”对他们来说都应该是“透明的”.“内存对齐”应该是编译器的“管辖范围”.编译器为程序中的每个“数据单元”安排在适当的位置上 ...
- C语言中内存对齐与结构体
结构体 结构体是一种新的数据类型,对C语言的数据类型进行了极大的扩充. struct STU{ int age; char name[15]; }; struct STU a; //结构体实例 str ...
- C语言中内存对齐
今天一考研同学问我一个问题,一个结构体有一个int类型成员和一个char类型成员,问我这个结构体类型占多少个字节,我直接编个程序给他看结果.这个结构体占八个字节,咦,当时我蛮纳闷的,一个int类型四个 ...
- Go中由WaitGroup引发对内存对齐思考
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 WaitGroup使用大家都会,但是其中是怎么实现的我们 ...
- 解析C语言结构体对齐(内存对齐问题)
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...
- C语言再学习之内存对齐
昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...
- C语言:内存字节对齐详解[转载]
一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...
随机推荐
- 软工网络15团队作业8——Beta阶段敏捷冲刺(Day5)
提供当天站立式会议照片一张 每个人的工作 1.讨论项目每个成员的昨天进展 赵铭: 进一步数据整理,写入数据库. 吴慧婷:主页面.查单词页面的改进.背单词界面改进. 陈敏: 单词学习功能及该界面按钮功能 ...
- 总结MySQL修改最大连接数的两个方式
最大连接数是可以通过mysql进行修改的,mysql数据库修改最大连接数常用有两种方法,今天我们分析一下这两种方法之间的特点和区别,以便我们能更好的去维护mysql.下面我们来看一下mysql修改最大 ...
- js异步上传图片
<!DOCTYPE html><html xmlns = "http://www.w3.org/1999/xhtml" ><head><m ...
- 查看ROS最大并发连接数量
命令行下输入以下 ip firewall connection tracking print interval 1 max-entries这个就是最大的并发连接数量 退出按Q
- sql学习. case + group by 都干了啥子事情
select case pref_name when 'fudao' then 'siguo' when 'xiangchuan' then 'siguo' when 'aiyuan' then 's ...
- 多线程同步与并发访问共享资源工具—Lock、Monitor、Mutex、Semaphore
“线程同步”的含义 当一个进程启动了多个线程时,如果需要控制这些线程的推进顺序(比如A线程必须等待B和C线程执行完毕之后才能继续执行),则称这些线程需要进行“线程同步(thread synchro ...
- HDU4292_Food
给出一些人,一些食物,一些饮料,每个人都只喜欢喝某些饮料,吃某些食品,每个食品和饮料都有一定的数量,现在问最多能满足多少人的需求. 注意理解题意了,每个人只需要要拿一个食物和一个饮料即可,这题目说得好 ...
- BZOJ1064 NOI2008假面舞会(dfs树)
将图中的环的长度定义为正向边数量-反向边数量,那么答案一定是所有环的环长的共同因子.dfs一下就能找到图中的一些环,并且图中的所有环的环长都可以由这些环长加加减减得到(好像不太会证).如果有环长为1或 ...
- [UVALive 3983] Robotruck
图片加载可能有点慢,请跳过题面先看题解,谢谢 设状态 \(f[i][j]\) 为,当前垃圾序号为 \(i\) ,当前承重为 \(j\) 的最小路程,好的这道题做完了 O(NC) G烂 $ $ 我们这样 ...
- 域hash值破解的总结经验
1.vsssown.vbs拷贝域数据库: 1.1上传vssown.vbs文件 上传cscript.exe和vssown.vbs到域服务器上 1.2创建快照 reg query HKEY_LOCAL_M ...