struct 大小计算
结构体是一种复合数据类型,通常编译器会自动的进行其成员变量的对齐,已提高数据存取的效率。在默认情况下,编译器为结构体的成员按照自然对齐(natural alignment)条方式分配存储空间,各个成员按照其声明顺序在存储器中顺序存储。自然对齐是指按照结构体中成员size最大的对齐,在cl编译器下可以使用
#pragma pack(n)
来指定结构体的对齐方式。
默认对齐方式
在默认对齐方式下,结构体成员的内存分配满足下面三个条件
- 结构体第一个成员的地址和结构体的首地址相同
- 结构体每个成员地址相对于结构体首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节(internal adding)。
- 结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加填充字节(trailing padding)。
下面是一个示例:
struct s1{
char ch;
int a;
double b;
char c1;
};
struct s2{
char ch;
int a;
double b;
};
int main()
{
cout << "s1的大小: " << sizeof(struct s1) << endl;
cout << "ch的地址偏移是 " << offsetof(s1, ch) << endl;
cout << "a 的地址偏移是 " << offsetof(s1, a) << endl;
cout << "b 的地址偏移是 " << offsetof(s1, b) << endl;
cout << "c1的地址偏移是 " << offsetof(s1, c1) << endl;
cout << "=====================================" << endl;
cout << "s2的大小: " << sizeof(struct s2) << endl;
cout << "ch的地址偏移是 " << offsetof(s2, ch) << endl;
cout << "a 的地址偏移是 " << offsetof(s2, a) << endl;
cout << "b 的地址偏移是 " << offsetof(s2, b) << endl;
getchar();
return 0;
}
代码中 offsetof函数可以得到结构体成员相对于该结构体首地址的偏移量。
其运行结果如下图
对于结构体s1来说,
- ch是其第一个成员故其地址和结构体的地址是相同的也就是说偏移量为0;
- a是int型其大小为4个字节,按照条件(2) 结构体每个成员地址相对于结构首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节,所以其地址偏移应该是4,也就说编译器在第一个成员ch后面填充了3个字节。
- b是double型占8个字节,其地址偏移应该是8的整数倍,由于a的地址偏移是4其大小为4个字节,正好b的偏移地址是8,不需要填充字节。
- c1是char型占1个字节,偏移地址是16(b的偏移地址是8大小也是8,中间也没有填充字节)。
- 这时成员ch占1个字节后面有3个字节的填充,a占4个字节后面无填充,b占8个字节后面无填充,c1占1个字节,s1总的大小是\(1 + 3 + 4 + 8 + 1 = 17\)。按照条件(3)结构体总的大小需是其最大成员所占空间的整数倍,其最大的成员b占有8字节,17显然是不符合条件的,所以需要在结构体的末尾填充7个字节,最后结构体总的大小是24字节。
结构体s2和s1的成员是非常相似的,唯一的区别是其末尾没有最后7个字节的填充,所以其大小是16个字节,这里用于和s1做对比说明s1末尾的填充字节。
指定对齐方式
可以使用#pragma pack(N)来指定结构体成员的对齐方式
对于指定的对齐方式,其成员的地址偏移以及结构的总的大小也有下面三个约束条件
- 结构体第一个成员的地址和结构体的首地址相同
- 结构体每个成员的地址偏移需要满足:N大于等于该成员的大小,那么该成员的地址偏移需满足默认对齐方式(地址偏移是其成员大小的整数倍);N小于该成员的大小,那么该成员的地址偏移是N的整数倍。
- 结构体总的大小需要时N的整数倍,如果不是需要在结构体的末尾进行填充。
- 如果N大于结构体成员中最大成员的大小,则N不起作用,仍然按照默认方式对齐。
示例仍然是上面的s1和s2,不过使用
#pragma pack(4)
设定按照4字节对齐
运行结果
结果分析
- ch是其第一个成员故其地址和结构体的地址是相同的也就是说偏移量为0;
- a占4个字节,和设定的对齐方式相等,所以其地址偏移是其大小的整数倍为4。
- b占8个字节,大于设定的对齐方式4,所以其地址偏移是N的整数倍为8。
- c1占1个字节,小于设定的对齐方式,所以其地址偏移是其大小的整数倍为16。
- 总的大小17个字节,不是N(4)的整数倍,所以在结构体的末尾填充3个字节,总的大小为20个字节。
说明:
- 在使用#pragma pack设定对齐方式一定要是2的整数幂,也就是(1,2,4,8,16,...),不然不起作用的,仍然按照默认方式对齐。
- 当结构体中有其他的结构体作为成员时,计算最大成员是不能把结构体成员作为一个整体来计算,要看其每个成员的大小。
struct 大小计算的更多相关文章
- union 和struct大小计算
一.字节对齐 现代计算机的内存空间是按照字节(byte)来划分的,字节对齐的意思是在给特定变量类型分配内存空间的时候,变量的内存地址是它本身变量类型大小的整数倍.比如,给int类型的变量a分配地址空间 ...
- C++类所占内存大小计算
C++类所占内存大小计算 说明:笔者的操作系统是32位的. class A {}; sizeof( A ) = ? sizeof( A ) = 1明明是空类,为什么编译器说它是1呢? 空类同样可以实例 ...
- C语言精要总结-内存地址对齐与struct大小判断篇
在笔试时,经常会遇到结构体大小的问题,实际就是在考内存地址对齐.在实际开发中,如果一个结构体会在内存中高频地分配创建,那么掌握内存地址对齐规则,通过简单地自定义对齐方式,或者调整结构体成员的顺序,可以 ...
- C++类的大小计算汇总
C++中类涉及到虚函数成员.静态成员.虚继承.多继承.空类等. 类,作为一种类型定义,是没有大小可言的. 类的大小,指的是类的对象所占的大小.因此,用sizeof对一个类型名操作,得到的是具有该类型实 ...
- 结构体(struct)大小
结构体(struct)大小 本文参考链接:C语言结构体(struct)常见使用方法,链接中的实例代码经实践有几处不准确,本文在引用时已做更改 注意:在结构体定义时不能申请空间(除非是结构体变量),不可 ...
- Java对象的内存布局以及对象所需内存大小计算详解
1. 内存布局 在HotSpot虚拟机中,对象的内存布局可以分为三部分:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 1) 对象头(Header): ...
- (一一七)基本文件操作 -SDWebImage清除缓存 -文件夹的大小计算
在iOS的App沙盒中,Documents和Library/Preferences都会被备份到iCloud,因此只适合放置一些记录文件,例如plist.数据库文件.缓存一般放置到Library/Cac ...
- TensorFlow与caffe中卷积层feature map大小计算
刚刚接触Tensorflow,由于是做图像处理,因此接触比较多的还是卷及神经网络,其中会涉及到在经过卷积层或者pooling层之后,图像Feature map的大小计算,之前一直以为是与caffe相同 ...
- 【转载】【内存对齐(二)】__declspec( align(#) )的用法和大小计算
转自:http://www.cppblog.com/deercoder/archive/2011/03/13/141747.html 感谢作者! 在上面讲到了关于pack的内存对齐和计算方法,这里继续 ...
随机推荐
- 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRemoteDeviceFind
这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRemoteDeviceFind的使用如下: ...
- SSH学习笔记
Struts2登录模块处理流程: 浏览器发送请求http://localhost/appname/login.action,到web应用服务器: 容器接收到该请求,根据web.xml的配置,服务器将请 ...
- Android内存清理
直接上图吧! 获取文件大小 ,清理文件工具类 public class DataCleanManager { public static String getTotalCacheSize(Contex ...
- 编写一个基本的连接池来实现连接的复用&一些工程细节上的优化
package it.cast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQL ...
- HTTP method POST is not supported by this URL
修改提交页面的提交方式,修改method为get(在index页面中html标签 method="get") 示例代码修改后的代码: <form action="s ...
- Excel导入导出的业务进化场景及组件化的设计方案(上)
1:前言 看过我文章的网友们都知道,通常前言都是我用来打酱油扯点闲情的. 自从写了上面一篇文章之后,领导就找我谈话了,怕我有什么想不开. 所以上一篇的(下)篇,目前先不出来了,哪天我异地二次回忆的时候 ...
- VS轻松开发Node.js应用
PTVS开发团队又开发出一款可以在VS里编写Node.js应用程序的插件--NTVS(Node.js Tools for Visual Studio),开发者可以在VS里轻松开发Node.js应用. ...
- 仅此一文让你明白ASP.NET MVC 之View的显示(仅此一文系列二)
题外话 一周之前写的<仅此一文让你明白ASP.NET MVC原理>受到了广大学习ASP.NET MVC同学的欢迎,于是下定决心准备把它写成一个系列,以满足更多求知若渴的同学们.蒋金楠老师已 ...
- SQL Server 深入解析索引存储(下)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/非聚集索引 概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非 ...
- Apache Mina实战
Mina介绍 Mina可以用于快速的开发基于网络通信的应用,特别是在开发手机端的游戏应用时,使用的较为普遍.本文简单介绍了一个用Mina搭建的一个简易讨论组,通过该应用可以对Mina的基本用法用途有个 ...