对C语言内存对齐的初步了解
在解释内存对齐的作用前,先来看下内存对齐的规则:
1、 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。
2、 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
#pragma pack(n) 表示设置为n字节对齐。 VC6默认8字节对齐
以程序1为例解释对齐的规则 :
St1 :char占一个字节,起始偏移为0 ,int 占4个字节,min(#pragmapack()指定的数,这个数据成员的自身长度) = 4(VC6默认8字节对齐),所以int按4字节对齐,起始偏移必须为4的倍数,所以起始偏移为4,在char后编译器会添加3个字节的额外字节,不存放任意数据。short占2个字节,按2字节对齐,起始偏移为8,正好是2的倍数,无须添加额外字节。到此规则1的数据成员对齐结束,此时的内存状态为:
oxxx|oooo|oo
0123 4567 89 (地址)
(x表示额外添加的字节)
共占10个字节。还要继续进行结构本身的对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行,st1结构中最大数据成员长度为int,占4字节,而默认的#pragma pack 指定的值为8,所以结果本身按照4字节对齐,结构总大小必须为4的倍数,需添加2个额外字节使结构的总大小为12 。此时的内存状态为:
oxxx|oooo|ooxx
0123 4567 89ab (地址)
到此内存对齐结束。St1占用了12个字节而非7个字节。
St2 的对齐方法和st1相同,读者可自己完成。
内存对齐的主要作用是:
1、 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。具体原因稍后解释。
图一:

这是普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看待的。
图二:

CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory accessgranularity(粒度)本人把它翻译为“内存读取粒度”。
假设CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:
1、数据从0字节开始
2、数据从1字节开始
再次假设内存读取粒度为4。
图三:

当该数据是从0字节开始时,很CPU只需读取内存一次即可把这4字节的数据完全读取到寄存器中。
当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。
图四:

此时CPU先访问一次内存,读取0—3字节的数据进寄存器,并再次读取4—5字节的数据进寄存器,接着把0字节和6,7,8字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。
这还属于乐观情况了,上文提到内存对齐的作用之一为平台的移植原因,因为以上操作只有有部分CPU肯干,其他一部分CPU遇到未对齐边界就直接罢工了。
对C语言内存对齐的初步了解的更多相关文章
- C语言内存对齐详解
一.字节对齐基本概念 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型 ...
- C语言内存对齐详解(2)
接上一篇:C语言内存对齐详解(1) VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式.VC 中提供了#pr ...
- C语言内存对齐详解(3)
接上一篇:C语言内存对齐详解(2) 在minix的stdarg.h文件中,定义了如下一个宏: /* Amount of space required in an argument list for a ...
- C语言内存对齐原理
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...
- C语言内存对齐(2)
前两天参加了360测试实习生的笔试,碰到了一个有关c语言内存对齐的题目,回来后实现了一下,下面是代码: #include <stdio.h> #include <stdlib.h&g ...
- c语言内存对齐问题
#include <stdio.h>#pragma pack(4)struct stu{char a;short b;int c;char d;};int main(){printf(&q ...
- C语言内存对齐
转:http://blog.csdn.net/embeddedman/article/details/7429976 首先由一个程序引入话题: 1 //环境:vc6 + windows sp2 2 ...
- C语言内存对齐对则
这篇文章讲的非常好 : http://blog.csdn.net/hairetz/article/details/4084088 用空间换时间, 规则 : 每个数据成员存储的起始位置都要是它的整数 ...
- go语言内存对齐
内存对齐 为保证程序顺利高效的运行,编译器会把各种类型的数据安排到合适的地址并占用合适的长度,这就是内存对齐 每种类型的对齐值就是他的内存边界 64位 类型 对齐边界 (对齐值) int8 1byte ...
随机推荐
- php面向对象成员方法(函数)练习
<?php header('content-type:text/html;charset=utf-8'); //成员方法的举例 /* ①添加sayHello 成员方法,输出 'hello' ②添 ...
- 抓包:MySQL Sniffer
1.依赖文件安装 依赖glib2-devel.libpcap-devel.libnet-devel [root@VMUest ~]# yum install cmake [root@VMUest ~] ...
- <scrapy爬虫>基本知识-修改链接-中间件
rules = ( Rule(LinkExtractor(allow=r'/films/\d+'),process_links='deal_links' ,callback='parse_maoyan ...
- <每日一题>题目8:文件备份V1.0
import os #备份文件的路径 file_address = input("输入需要备份文件所在的路径:") os.chdir(file_address) #备份文件命名 f ...
- 近期开发storm遇到一些问题的解决点
storm开发解决问题点1.kafka消费速度跟不上问题 这个问题可以从加大topic partition进行解决,可以在topic正在运行时候运行命令 ./kafka-topics --alter ...
- Java基础(业务问题)
幂等的处理方式 一.查询与删除操作是天然幂等 二.唯一索引,防止新增脏数据 三.token机制,防止页面重复提交 四.悲观锁 for update 五.乐观锁(通过版本号/时间戳实现, 通过条件限制 ...
- sscanf linux-c从一个字符串中读进与指定格式相符的数据
https://www.cnblogs.com/lanjianhappy/p/6861728.html 函数原型: Int sscanf( string str, string fmt, mixed ...
- 使用cmd查看windows端口占用情况,并关闭应用
在做开发的时候常常会遇到端口被占用的问题,下面是我在网上找的比较好用的一种关闭占用端口进程的方法 1.在运行中输入cmd打开dos命令窗口,比如我想找到端口8888对应的PID(通过PID找到相应的进 ...
- skyline中遍历fly工程树
在skyline二次开发过程中,做空间分析总是要去读取工程中的shp图层.假设想获取工程树中“建筑物”图层,图层结构如下: 传统的方法是: var itemId=SGWorld.ProjectTree ...
- 单例模式(Singleton)(单一实例)
单例模式基本要点: 用于确保一个类只有一个实例,并且这个实例易于被访问. 让类自身负责保存他的唯一实例.这个类可以保证没有其他实例创建,并且他可以提供一个访问实例的方法,来实现单例模式. (1)把构造 ...