美文网首页
字节对齐

字节对齐

作者: _我和你一样 | 来源:发表于2017-12-01 11:49 被阅读0次

什么叫做字节对齐?

对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。

对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐:

  • 数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。
  • 联合 :按其包含的长度最大的数据类型对齐。
  • 结构体: 结构体中每个数据类型都要对齐。

编译器是按照什么样的原则进行对齐的?

  1. 数据类型自身的对齐值:

对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,类型,其自身对齐值为4,double类型,其对齐值为8,单位字节。

  1. 结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
  1. 指定对齐值:#pragma pack (value)时的指定对齐值value。
  1. 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。

有效对齐值N是最终用来决定数据存放地址方式的值,最重要。

有效对齐N,就是表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。

第一个数据变量的起始地址就是数据结构的起始地址。

结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整

举例说明:

struct B
{
char b;
int a;
short c;
};

编译器默认情况下会对这个struct作自然边界对齐。

假设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。

第一个成员变量b的自身对齐值是1,比指定或者默认指定对齐值4小,所以其有效对齐值为1,所以其存放地址0x0000符合0x0000%1=0.

第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4,所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,复核0x0004%4=0,且紧靠第一个变量。

第三个变量c,自身对齐值为2,所以有效对齐值也是2,可以存放在0x0008到0x0009这两个字节空间中,符合0x0008%2=0。所以从0x0000到0x0009存放的都是B内容。

再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求,0x0009到0x0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。

故B从0x0000到0x000B共有12个字节,sizeof(struct B)=12;

例子:

#pragma pack (2) /*指定按2字节对齐*/
struct C
{
char b;
int a;
short c;
};
#pragma pack () /*取消指定对齐,恢复缺省对齐*/

第一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合0x0000%1=0;

第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续字节中,符合0x0002%2=0。

第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放
在0x0006、0x0007中,符合0x0006%2=0。所以从0x0000到0x00007共八字节存放的是C的变量。又C的自身对齐值为4,所以C的有效对齐值为2。又8%2=0,C只占用0x0000到0x0007的八个字节。

所以sizeof(struct C)=8.

案例分析

例子:联合体

union u
{
 double a;
 int b;
}; 

union u2
{
 char a[13];
 int b;
}; 

union u3
{
 char a[13];
 char b;
}; 

cout<<sizeof(u)<<endl; // 8cout<<sizeof(u2)<<endl; // 16cout<<sizeof(u3)<<endl; // 13

联合体按其包含的长度最大的数据类型对齐。联合体的内存不会为了所有成员安排,而是只取最大的成员的所需内存大小,每次只能使用其中一个成员。

联合体的内存除了取最大成员内存外,还要保证是所有成员类型size的最小公倍数

u中 a的数据类型为double,长度为8,有效对齐值为8,b的有效对齐值是4,而选择按8对齐。复核是8的整数倍。

u2中,a占据13个字节,包含长度最大,但char的有效对齐值是1.int的有效对齐值是4,所以复核13%4 !=0 还要补3个字节。所以共16个子节大小。

u3中,a占据13个字节,包含长度最大,a和b的有效对齐值都是1 复核13%1===0

所以以上分别是 8 16 13

例子:结构体

struct s1
{
 char a;
 double b;
 int c;
 char d; 
}; 

struct s2
{
 char a;
 char b;
 int c;
 double d;
}; 

cout<<sizeof(s1)<<endl; // 24cout<<sizeof(s2)<<endl; // 16

s1:

a的有效对齐值是1,占据一个字节

b的有效对齐值是8,前面补7个字节,占据8个字节。

c的有效对齐值是4,

D的有效对齐值是1

复核 1+7+8+4+1=21 21%8 == 5;

所以最后要补3个字节。最终结果是24;

s2:

a的有效对齐值是1,占据1个字节

b的有效对齐值是1,占据1个字节

c的有效对齐值是4,前面需要补2个字节。占据4个字节。

d的有效对齐值是8,占据8个字节

1+1+2+4+8=16

复核16%8==0

所以结果是16.

由此可见,结构体中,相同的数据类型,不同的顺序结果也会不一样。我们通常会把长度多的放在最后。通常会减少内存占用。

相关文章

  • 字节对齐与大端小端与内存区域划分

    字节对齐 C语言字节对齐C语言字节对齐/7213465 大端小端 字节序(大小端)详解从高低地址和高低位开始理解(...

  • iOS 技术

    结构体的字节对齐和OC对象的字节对齐? instance(实例对象)、class(类对象)、meta-class(...

  • 字节对齐

    为什么字节对齐: 体系结构的对齐和不对齐,是在时间和空间上的一个权衡。对齐节省了时间。假设一个体系结构的字长为w,...

  • 字节对齐

  • 字节对齐

    什么叫做字节对齐? 对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐...

  • 字节对齐

    字节对齐的细节和编译器实现相关,一般满足三个准则: 1.结构体变量的首地址能够被其最宽的基本类型成员的大小所整除 ...

  • 字节对齐

    总原则:结构体变量占据的内存单元的个数应当大于等于其内部所有数据成员占据内存单元数的和。 出于效率的考虑,C预言引...

  • 字节对齐

    概述 字节对齐也称为字节填充,它是C++编译器的一种技术手段,主要目的是为了在空间和复杂度上达到平衡。简单而言,是...

  • #字节对齐

    [TOC] 什么是字节对齐(可以跳过) 现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类...

  • c语言结构体对齐

    1.什么是字节对齐 结构体里面一般会按照某种规则去进行字节对齐默认规则如下:对齐是按照结构体中长度最长的变量来对齐...

网友评论

      本文标题:字节对齐

      本文链接:https://www.haomeiwen.com/subject/obgibxtx.html