struct和union占用内存详解
来源:互联网 发布:中学生网络成瘾 编辑:程序博客网 时间:2024/06/05 03:16
一、struct与union占用内存
1.1 struct内存对齐
1.1.1 问题引入
代码如下:
#include <iostream>using namespace std;struct Test_A{ char x; char y; int z;};struct Test_B{ char x; int z; char y;};struct Test_C{ int z; char x; char y;};int main(){ struct Test_A a; memset(&a, 0, sizeof(a)); struct Test_B b; memset(&b, 0, sizeof(b)); struct Test_C c; memset(&c, 0, sizeof(c)); // Print the memory size of the struct cout << sizeof(a) << endl; // 8 Bytes cout << sizeof(b) << endl; // 12 Bytes cout << sizeof(c) << endl; // 8 Bytes return 0;}
上述代码输出结果为:
sizeof(a) = 8 Bytes;
sizeof(b) = 12 Bytes;
sizeof(c) = 8 Bytes.
为什么只是改变了结构体中的成员顺序,结果就不一样了?因为编译器的内存对齐机制。
1.1.2 内存对齐
1. 内存对齐问题存在于:
理解struct和union等复合结构在内存中的分布。
2. 内存对齐的目的:
- 平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 - 提高内存访问效率。
CPU在访问内存时是按块读取的。块的大小称为memory access granularity(内存存取粒度)。访问已对齐的内存只需1个指令周期;而访问未对齐的内存需2个指令周期,可能需要额外的数据选取、剔除操作,大大降低了效率。
常见编译器的内存存取粒度如下表,在windows(32)/VC6.0下,n的取值可以为1、2、4、8,默认情况下为8。在linux(32)/GCC下,n的取值只能为1、2、4,默认情况下为4:
3. 内存对齐的定义:
计算机系统对基本类型数据在内存中存放的位置有限制,要求这些数据的首地址是内存存取粒度n(通常为4或8)的倍数,这就是所谓的内存对齐。内存对齐是编译器做的事情。这个值n在不同的CPU平台下、不同的编译器下表现也有所不同。可通过预编译命令`#pragma pack(n)`,n = 1,2,4,8,16.来进行修改。
4. 内存对齐的规则:
- 第一条:第1个数据成员置于offset为0的位置,每个数据类型的偏移量必须是min(#pragma pack(n)中的n, 数据自身占用的字节数)的倍数;
- 第二条:数据成员对齐(局部对齐)后,结构体(联合体)还需进行整体对齐,对齐将按照min(#pragma pack(n)中的n, 数据成员中的最大长度)进行,即结构体(联合体)占用内存应为上述min的倍数。
5. 实例演示:
#include <iostream>using namespace std;# pragma pack(1) // 设置对齐系数分别为1、2、4、8、16struct Test{ char x1; // 1 Byte double x2; // 8 Bytes short x3; // 2 Bytes float x4; // 4 Bytes char x5; // 1 Byte};int main(){ Test test; cout << sizeof(test) << endl; return 0;}
代码输出结果为:
n = 1时,输出16 Bytes;
n = 2时,输出18 Bytes;
n = 4时,输出24 Bytes;
n = 8时,输出32 Bytes;
n = 16时,输出32 Bytes。
分析如下:
注意:按n对齐的意思是,占用地址的偏移量为n的倍数。
n = 1时,首先使用规则1进行局部对齐:
x1,1 ≤ 1,按1对齐,占用0;
x2,8 > 1,按1对齐,占用1,2,3,4,5,6,7,8;
x3,2 > 1,按1对齐,占用9,10;
x4,4 > 1,按1对齐,占用11,12,13,14;
x5,1 ≤ 1,按1对齐,占用15;
最后使用规则2进行整体对齐:
x2占用的内存最大,为8 Bytes,8 > 1,整体按照1对齐,16 % 1 = 0。所以在n = 1 时,struct Test占用16 Bytes。如下图:
n = 2时,首先使用规则1进行局部对齐:
x1,1 ≤ 2,按1对齐,占用0;
x2,8 > 2,按2对齐,占用2,3,4,5,6,7,8,9;
x3,2 ≤ 2,按2对齐,占用10,11;
x4,4 > 2,按2对齐,占用,12,13,14,15;
x5,1 ≤ 2,按1对齐,占用16;
最后使用规则2进行整体对齐:
x2占用的内存最大,为8 Bytes,8 > 2,整体按照2对齐,17 % 2 != 0,补齐到18 Bytes。所以在n = 2 时,struct Test占用18 Bytes。如下图:
n = 4时,首先使用规则1进行局部对齐:
x1,1 ≤ 4,按1对齐,占用0;
x2,8 > 4,按4对齐,占用4,5,6,7,8,9,10,11;
x3,2 ≤ 4,按2对齐,占用12,13;
x4,4 ≤ 4,按4对齐,占用16,17,18,19;
x5,1 ≤ 4,按1对齐,占用20;
最后使用规则2进行整体对齐:
x2占用的内存最大,为8 Bytes,8 > 4,整体按照4对齐,21 % 4 != 0,补齐到24字节。所以在n = 4 时,struct Test占用24 Bytes。如下图:
n = 8时,首先使用规则1进行局部对齐:
x1,1 ≤ 8,按1对齐,占用0;
x2,8 ≤ 8,按8对齐,占用8,9,10,11,12,13,14,15;
x3,2 ≤ 8,按2对齐,占用16,17;
x4,4 ≤ 8,按4对齐,占用20,21,22,23;
x5,1 ≤ 8,按1对齐,占用24;
最后使用规则2进行整体对齐:
x2占用的内存最大,为8 Bytes,8 ≤ 8,整体按照8对齐,25 % 8 != 0,补齐到32字节。所以在n = 8 时,struct Test占用32 Bytes。如下图:
n = 16时,首先使用规则1进行局部对齐:
x1,1 ≤ 16,按1对齐,占用0;
x2,8 ≤ 16,按8对齐,占用8,9,10,11,12,13,14,15;
x3,2 ≤ 16,按2对齐,占用16,17;
x4,4 ≤ 16,按4对齐,占用20,21,22,23;
x5,1 ≤ 16,按1对齐,占用24;
最后使用规则2进行整体对齐:
x2占用的内存最大,为8 Bytes,8 ≤ 16,整体按照8对齐,25 % 16 != 0,补齐到32字节。所以在n = 16 时,struct Test占用32 Bytes。如下图:
1.2 Union内存对齐
1.2.1 什么是union
翻译为共用体或者联合体。union的成员变量都是在同一地址存放的,即使用覆盖技术,使成员变量相互覆盖,共同占用同一段内存。
union具有以下特点:
- 同一个内存段可以用来存放多种不同类型的成员,但是同一时刻只有一个成员起作用;
- union中起作用的是最后一个存放的成员,在存入一个新成员后,原有的变量就会失去作用;
- union中所有成员的起始地址相同。
1.2.2 实例
定义如下的union:
#include <iostream>using namespace std;union test{ char mark; long num; float score;}a;int main(){ // cout<<a<<endl; // wrong a.mark = 'b'; cout<<a.mark<<endl; // 输出'b' cout<<a.num<<endl; // 98 字符'b'的ACSII值 cout<<a.score<<endl; // 输出错误值 a.num = 10; cout<<a.mark<<endl; // 输出换行('\n'的ASCII值为10) cout<<a.num<<endl; // 输出10 cout<<a.score<<endl; // 输出错误值 a.score = 10.0; cout<<a.mark<<endl; // 输出空 cout<<a.num<<endl; // 输出错误值 cout<<a.score<<endl; // 输出10 return 0;}
1.2.3 占用内存
在32位机器上,sizeof(union test)
结果为4。其内存结构示意图如下:
对于union所占用的内存大小,需要考虑内存对齐的问题,但是大体来说,union变量所占用的内存长度等于最长的成员的内存长度。
与之对比,大体上来说,结构体struct所占用的内存为各个成员的占用的内存之和(当然也需要考虑内存对齐的问题了)。定义以下结构体struct test2:
struct test2{ char mark; long num; float score;}b;
其内存结构如下:
二、参考内容:
[1] C、C++内存对齐
http://www.jellythink.com/archives/413
[2] C、C++中union用法总结
http://www.jellythink.com/archives/468
[3] 内存对齐的规则以及作用
http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html
- struct和union占用内存详解
- 关于union和struct的内存分配
- 关于union和struct的内存分配
- 关于union和struct的内存分配
- Union和Struct的内存分配
- Union和Struct的内存分配
- Union和Struct的内存分配
- struct和union的内存分配
- 对《C语言:内存字节对齐详解——struct 和 union 》的理解
- struct union 内存对齐
- struct union 内存分配
- union struct 内存对齐
- struct/union内存对齐
- 大端小端区别、Union和Struct的内存分配
- 大端小端区别、Union和Struct的内存分配
- 大端小端区别、Union和Struct的内存分配
- sizeof(union) 、sizeof(struct) 和内存对齐技术
- 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
- java爬虫之抓取城市数据
- Keil MDK 和 IAR 两款ARM开发工具区别比较
- 整理docker及Hadoop脚本(四)-在docker集群集群中一键式部署hadoop
- 一个ReverseMe的算法分析
- 数据库补充学习之基础补充
- struct和union占用内存详解
- Python入门记——列表2
- Ajax技术
- Mongo数据库安装与入门
- 作业1
- C++11 右值引用和转移语义
- ngrok集成在本地Node.js项目服务器,实现F5调试即可自动打开浏览器且通过外网可访问本地服务器。
- OpenWrt源码分析之ubus
- 正向代理和反向代理