内存对齐

原创 2015年11月21日 10:15:10

一个常见的例子

struct s1{
    char a;
    char b;
    int c;
}
struct s2{
    char a;
    int c;
    char b;
}

sizeof(s1) = 8;
sizeof(s2) = 12;

内存对齐

内存地址对齐,是一种在计算机内存中排列数据、访问数据的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐

对于基本数据类型,其地址是内存对齐的:基本类型数据对齐就是数据在内存中的偏移地址必须等于一个字的倍数
而结构体对齐:为了保证访问结构体数据的性能,可能需要在上一个数据结束的地方和当前数据开始的地方插入一些纯粹占位的字符。包括结构体内部元素类型的对齐和结构体本身的对齐

内存对齐的规则为:

1、 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。
2、 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

看上面中s2的例子,假设编译默认pack(8), a偏移0,c为int,所以其偏移应该是是min(8,4)=4 ,所以需要在a,c之间插入3个填充字节,再看b,其偏移为min(8,1)=1;所以不用考虑。已有的数据占了1+3+4+1=9字节。现在考虑第二条规则,结构体本身也要对齐(这样是为了当声明结构体数组时,能够访问更快),最大的数据成员为int,4字节,min(8,4)=4,所以要加上3字节,9+3=12凑成4的倍数。所以sizeof(s2)=12;
所以上面结构体实际为

struct s2{
    char a;
    char pad[3];
    int c;
    char b;
    char pad[3];
}

那么一个例子
struct{ char a; char b;} 其 size是2bytes. 而不是一定要填充到4字节。因为根据第二条,对齐按char的数据长度来,就是char的倍数即可,所以是 2bytes.

注意数组元素之间是没有填充位的,加了反而会浪费空间,无论声明基本元素还是结构体元素的数组。如果是类型长度小于等于4字节,那么不需要加填充位,因为一次访问一个字就可以把元素取出来,如果大于4字节,那么本来就需要多次访问。
为了优化,重新排列结构体元素顺序或者故意加一些填充位也是可以的。比如OpenCV的图像像素,行首的地址通常需要字节对齐,所以行与行之间的偏移 widthStep不一定等于width*channels, 而是 widthStep = (width*channels + align-1) /align *align;

可以用 #pragma pack来改变编译器默认的内存设置

#pragma pack(push) 
#pragma pack(2)
// your struct define
#pragma pack(pop)

内存对齐的好处

  • 加快数据的访问速度。

计算机内部32位的地址总线,32位的数据总线,所以每次能读取4个字节的数据,而并非一个字节一个字节读取。最低2位A[0],A[1]是不用于寻址,A[2-31]才能存储器相连,因此只能访问4的倍数地址空间
假设一个int 4字节,如果其地址是对齐的(假设是0x3FFFFFF0),那么只需要一次访问内存就能获取4个字节,但是如果其地址是非对齐的(比如0x3FFFFFF1),那么需要连续2次访问内存,分别访问0x3FFFFFF1获得后面3个字节和0x3FFFFFF4获得前面1个字节,并合起来,然后才能获取这个int数据。而由于CPU的处理速度远高于访问内存的速度,所以显然前者要快很多

  • 便于程序移植。而在有些CPU架构上,并不支持非对齐地址的访问,所以如果代码中字节不对齐,对程序移植也会有影响

参考:
内存地址对齐
内存对齐的规则以及作用

C/C++ 内存对齐原则及作用

struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成...
  • chy19911123
  • chy19911123
  • 2015年10月04日 09:50
  • 4210

C语言深度解剖读书笔记(3.结构体中内存对齐问题)

很多人都觉得内存对齐这个问题很难,很不好算,总算错,其实我想说只要你画一画就没那么难了。好了,进入正题。 本节知识点: 1.结构体为什么要内存对齐(也叫字节对齐): 其实我们都知道,结构体只是一...
  • qq418674358
  • qq418674358
  • 2013年08月24日 00:28
  • 6353

为什么要内存对齐

当我们听到”内存对齐“这个概念时,从字面意思来看,很容易理解。那就是让内存对齐。        当然  就会有人说  你这不是废话 ??         现在我就来说一说为什么要内存对齐以及怎么个对齐...
  • l_tudou
  • l_tudou
  • 2016年07月22日 23:40
  • 745

五分钟搞定内存对齐。

写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢?讲讲字节对齐吧.   /*******************...
  • me4weizhen
  • me4weizhen
  • 2016年09月19日 23:53
  • 1029

内存对齐以及如何关闭内存对齐

内存对齐以前接触过,知道有这么回事,昨天面试,面试官问了一个结构体内存分配相关的问题: struct _A{ int a; int b; char c; }A; sizeof(A)=?(32位机器) ...
  • a1205137569
  • a1205137569
  • 2015年10月08日 09:28
  • 403

内存对齐宏ALIGN

      对于正整数2^n(n>1)来说,存在这样的特性,如果整数X是2^n的整数倍,则X的二进制形式的低n位为0, 如果X不是2^n的整数倍,则X与(~(2^n-1))进行与运算可以得到一个...
  • qwaszx523
  • qwaszx523
  • 2017年02月23日 17:14
  • 248

对内存对齐的深一步理解

接触内存对齐这个概念,也有三四年了。不过由于我工作后一直做游戏服务器,都是在x86架构的机子上写代码,也没怎么注意内存对齐。使用最多的估计也就是面试时经常问结构体大小。最近在写自己服务器框架的二进流读...
  • weiyuefei
  • weiyuefei
  • 2016年08月05日 14:17
  • 1666

内存对齐与内存分配原则

首先讲一个概念—-内存对齐一种提高内存访问速度的策略,cpu在访问未对其的内存需要经过两次内存访问,而经过内存对齐一次就可以了。(?)打个比方就是:操作系统在访问内存时,每次读取一定的长度(这个长度是...
  • tingyun_say
  • tingyun_say
  • 2016年05月18日 14:30
  • 2291

gcc的内存对齐

原文在这里:http://blog.chinaunix.net/uid-7319742-id-2059621.html CPU以字节为单位编址,而C语言指针以指向的数据类型长度作自增和自减。 ...
  • ylluo_hust
  • ylluo_hust
  • 2014年03月16日 18:21
  • 632

内存对齐例子

具体的理论内容 神马是内存对齐以及为何要内存对齐请看http://blog.csdn.net/kokodudu/article/details/11918219 上面这个连接 将的相当理论 我给...
  • u010566813
  • u010566813
  • 2015年09月17日 01:00
  • 291
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:内存对齐
举报原因:
原因补充:

(最多只允许输入30个字)