结构体是一种复合数据类型,通常编译器会自动的进行其成员变量的对齐,已提高数据存取的效率。在默认情况下,编译器为结构体的成员按照自然对齐(natural alignment)条方式分配存储空间,各个成员按照其声明顺序在存储器中顺序存储。自然对齐是指按照结构体中成员size最大的对齐,在cl编译器下可以使用

#pragma pack(n)
来指定结构体的对齐方式。

默认对齐方式

在默认对齐方式下,结构体成员的内存分配满足下面三个条件

  1. 结构体第一个成员的地址和结构体的首地址相同
  2. 结构体每个成员地址相对于结构体首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节(internal adding)。
  3. 结构体总的大小要是其成员中最大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来说,

  1. ch是其第一个成员故其地址和结构体的地址是相同的也就是说偏移量为0;
  2. a是int型其大小为4个字节,按照条件(2)结构体每个成员地址相对于结构首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节,所以其地址偏移应该是4,也就说编译器在第一个成员ch后面填充了3个字节。
  3. b是double型占8个字节,其地址偏移应该是8的整数倍,由于a的地址偏移是4其大小为4个字节,正好b的偏移地址是8,不需要填充字节。
  4. c1是char型占1个字节,偏移地址是16(b的偏移地址是8大小也是8,中间也没有填充字节)。
  5. 这时成员ch占1个字节后面有3个字节的填充,a占4个字节后面无填充,b占8个字节后面无填充,c1占1个字节,s1总的大小是1+3+4+8+1=17。按照条件(3)结构体总的大小需是其最大成员所占空间的整数倍,其最大的成员b占有8字节,17显然是不符合条件的,所以需要在结构体的末尾填充7个字节,最后结构体总的大小是24字节。
  6. 结构体s2和s1的成员是非常相似的,唯一的区别是其末尾没有最后7个字节的填充,所以其大小是16个字节,这里用于和s1做对比说明s1末尾的填充字节。

指定对齐方式

可以使用#pragma pack(N)来指定结构体成员的对齐方式

对于指定的对齐方式,其成员的地址偏移以及结构的总的大小也有下面三个约束条件

  1. 结构体第一个成员的地址和结构体的首地址相同
  2. 结构体每个成员的地址偏移需要满足:N大于等于该成员的大小,那么该成员的地址偏移需满足默认对齐方式(地址偏移是其成员大小的整数倍);N小于该成员的大小,那么该成员的地址偏移是N的整数倍。
  3. 结构体总的大小需要时N的整数倍,如果不是需要在结构体的末尾进行填充。
  4. 如果N大于结构体成员中最大成员的大小,则N不起作用,仍然按照默认方式对齐。

示例仍然是上面的s1和s2,不过使用

#pragma pack(4)
设定按照4字节对齐

运行结果:

结果分析

  1. ch是其第一个成员故其地址和结构体的地址是相同的也就是说偏移量为0;
  2. a占4个字节,和设定的对齐方式相等,所以其地址偏移是其大小的整数倍为4;
  3. b占8个字节,大于设定的对齐方式4,所以其地址偏移是N的整数倍为8;
  4. c1占1个字节,小于设定的对齐方式,所以其地址偏移是其大小的整数倍为16;
  5. 总的大小17个字节,不是N(4)的整数倍,所以在结构体的末尾填充3个字节,总的大小为20个字节。

说明:

  1. 在使用#pragma pack设定对齐方式一定要是2的整数幂,也就是(1,2,4,8,16,…),不然不起作用的,仍然按照默认方式对齐。
  2. 当结构体中有其他的结构体作为成员时,计算最大成员是不能把结构体成员作为一个整体来计算,要看其每个成员的大小。

转载自:
https://www.cnblogs.com/wangguchangqing/p/4853438.html
Brook@CV
Brook_icv

如何计算结构体大小?相关推荐

  1. 图解如何计算结构体大小

    首先来看这样一个例子: struct X {char a; // 1 byteschar padding1[3]; // 3 bytesfloat b; // 4 bytesint c; // 4 b ...

  2. C语言 如何计算结构体的大小

    无嵌套结构体的大小计算 如何计算结构体的大小? 由于存储变量地址对齐的问题,计算结构体大小的3条规则: 1.结构体变量的首地址,必须是结构体变量中的"最大基本数据类型成员所占字节数" ...

  3. C语言 计算结构体大小

    本文主要参考:结构体内存对齐(如何计算结构体的大小) 前言 数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数. 结构体中的成员可以是不同的数据类型, ...

  4. C语言结构体-大小,对齐,填充,使用及其他

    C语言结构体-大小,对齐 C语言中的结构体(struct)的定义 在C语言中,最常用的数据结构就是结构体了,结构体也是其它数据结构(比如链表等)的基础,结构体的使用非常简单. 比如,定义一个结构体: ...

  5. 位结构体+大小端模式

    位结构体+大小端模式 位结构是一种特殊的结构, 在需按位访问一个字节或字的多个位时, 位结构比按位运算符更加方便   位结构定义的一般形式为:  struct  位结构名{  数据类型 [变量名]: ...

  6. 使用sizeof()计算结构体大小

    下面代码的输出结果是: #include <iostream> using namespace std; #pragma pack(4) struct T{ char a; short b ...

  7. C语言的sizeof运算符计算结构体大小

    C语言的sizeof运算符运算规则 sizeof运算符 **sizeof 是一个运算符,不是函数(方法).** 例子: 当想打印一个变量的存储区域大小时,可以直接写 int a = 5; printf ...

  8. 结构体大小,你真的知道吗?

    结构体大小,你真的知道吗? 编译环境:vs2019 结构体,顾名思义是一个包含多种类型的体块.在使用结构体时,我们定义一些变量让我们更容易得到想要的结果,比如 : struct Stu {char n ...

  9. 【C语言】一文搞定如何计算结构体的大小----结构体内存对齐规则

    要搞定如何正确地计算一个结构体的大小,我们就要深刻理解结构体内存对齐规则: 结构体内存对齐规则: 1.结构体的第一个成员永远在结构体起始位置偏移量为0的位置: 2.结构体成员从第二个成员开始,总是放在 ...

最新文章

  1. 算法---计数质数(Java)
  2. c语言编程 三角波,周期矩形波、周期锯齿波、周期三角波,C语言程序.doc
  3. python百度地图api经纬度_从百度地图API接口批量获取地点的经纬度
  4. 分析BootstrapClassLoader/ExtClassLoader/AppClassLoader的加载路径 及父委托机制
  5. UILabel教程 touch 事件
  6. 解决Mac无法写入U盘问题
  7. 计算机管理中不显示u盘,优盘不显示,教您优盘不显示处理方法
  8. ZNS : 解决传统SSD问题的高性能存储栈设计(fs-->io-->device)
  9. TypeError: date.locale is not a function
  10. halcon学习和实践(颜色筛选)
  11. 立创EDA仿真入门1 基本操作
  12. JavaScript进阶(6)-全选练习
  13. (原创)C# LRC复读机-1
  14. 游戏思考04总结:针对帧、状态、物理同步的总结(之前写的太长,现在简略下)
  15. 笨方法学python3怎么样_在python3中如何实现《笨方法学Python》ex11中的效果
  16. JCIM2021 | MolGPT : 基于Transformer-Decoder的分子生成
  17. 2021年焊工(高级)新版试题及焊工(高级)证考试
  18. python编程无师自通pdf_Python编程无师自通:专业程序员的养成 PDF下载
  19. 这篇文章会让你熟悉文件的各种操作,让你对文件的认识更加深入【c语言】
  20. php eth erc20,【Ethereum】以太坊ERC20 Token标准完整说明

热门文章

  1. 好程序员Python培训分享Python系列之分支结构
  2. pxe+kickstart
  3. 2022年智慧社区整体设计建设解决方案(ppt可编辑)
  4. OpenGL坐标变换及其数学原理,两种摄像机交互模型(附源程序)
  5. 《大话计算机》助推国产半导体浴火重生!
  6. 046ToolStrip类
  7. 抖音带货5天千粉开橱窗!
  8. Bandizip Archiver——新秀解压压缩工具!
  9. 将手机作为电脑硬件监视器
  10. CS231n学习记录Lec8 Training训练神经网络(下)