概述
问题:- struct Foo1
- {
- char a;
- char b;
- int c;
- }
复制代码
- 32位系统中,Foo1的对象在内存中占用多少内存?若是改变变量a,b,c在内存中的位置顺序,内存大小会变化么?
- 什么是内存对齐?
- 为什么要内存对齐?
- 如何内存对齐?
创建结构体Foo
- struct Foo
- {
- int a;
- int b;
- }
复制代码 查看Foo的内存布局
1>class Foo size(8):
1> +---
1> 0 | a
1> 4 | b
1> +---
在32位的系统中,int占4个字节,Foo内存布局占用8个字节内存。
创建结构体Foo1,Foo2,Foo3
- struct Foo1
- {
- char a;
- char b;
- int c;
- };struct Foo2{ char a; int c; char b;};struct Foo3{ int c; char a; char b;};
复制代码 查看Foo1,Foo2,Foo3的内存布局
1>class Foo1 size(8):
1> +---
1> 0 | a
1> 1 | b
1> | alignment member (size=2)
1> 4 | c
1> +---
1>class Foo2 size(12):
1> +---
1> 0 | a
1> | alignment member (size=3)
1> 4 | c
1> 8 | b
1> | alignment member (size=3)
1> +---
1>class Foo3 size(8):
1> +---
1> 0 | c
1> 4 | a
1> 5 | b
1> | alignment member (size=2)
1> +---
- Foo1占用8个字节,对齐2个字节。
- Foo2占用12个字节,a与b后各对齐3个字节。
- Foo3占用8个字节,对齐2个字节
内存对齐会影响内存的分配,以上结构体的内存大小不是6个字节。
内存对齐
现代计算机中内存空间都是按照 byte 划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数。
内存对齐的意义
跨平台
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
提升性能
0 0 0 1 1 1 1 0 --不对齐
0 0 0 0 1 1 1 1 --对齐
内存对齐在不同环境下对性能的提升不尽相同,一种情况是:假使32位系统下,处理器读取内存的粒度为4字节。未对齐内存需要读取两次内存,并进行内存剔除,且有可能引发OS异常处理。
内存对齐规则
内存对齐是编译器完成的,不同平台不同编译器内存对齐规则可能不同。
特定平台的编译器都有默认对齐系数。gcc中默认#pragma pack(4),可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变这一系数。
有效对其值:是给定值#pragma pack(n)和结构体中最长数据类型长度中较小的那个。有效对齐值也叫对齐单位。
- 结构体第一个成员的偏移量为0,后面每个成员相对于结构体首地址的偏移量是该成员大小与有效对齐值中较小那个值的整数倍,不满足条件则编译器会在成员之间填充字节以满足条件。
- 结构体的总大小必须是有效对齐值的整数倍,不满足条件则编译器会在成员之间填充字节以满足条件。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |