sizeof与struct——求结构体大小的计算方法

sizeof浅析(一)——求结构体大小 这篇文章讲了sizeof求结构体大小的计算方法,并给出可以套用的准则:

一、存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:

(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

二、 对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:

(1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
(2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

为什么?

但是编译器为什么要这么做,以下是我的理解。

为什么要对齐?

因为在32位操作系统(虽然64位操作系统,但是为了保证兼容性,编程仍然主要考量32位)中,数据总线是32位,地址总线是32位。
地址总线是32位,意味着寻址空间是按4递增的;数据总线32位意味着一次可读写4byte
考虑这样一个结构体

struct stu1
{   char c1;   int i;  char c2;
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

不对齐就意味着,当我们执行stu1.i 时,需要读取内存两次。而对齐后,就只需要读取一次,众所周知,I/O操作是很耗时的,编译器做出对齐的选择也就好理解。

为什么不完全按照4字节对齐的?

既然对齐可以避免上述的问题,为什么不将所有存储小于4byte的数据类型(char, short等)统统按4byte对齐呢?
考虑这样一个结构体

struct stu2
{   char c;   short s;int i; double d;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


为什么编译器采用B方案,而不采用A方案?
还是因为32数据线一次读取4个字节,
采用方案A,读取stu2.c,或者stu2.s,要一次读取4个byte,再舍弃无关内存的数据。
采用方案B,读取stu2.c,或者stu2.s,也是要一次读取4个byte,再舍弃无关内存中的数据。
同样的I/O操作,相比之下,明显方案B更节省内存。

补充: 如上图中,所示8字节的数据类型,比如double, long long,必须要读取两次内存。

明白这两点,再回看上面结构体大小的计算方法,就简单多了,也不用死记烂背了。
另外,写代码时也知道怎样节省内存了(虽然大多数时间不用考虑这点)。

结构体为什么要4字节对齐相关推荐

  1. NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构...

    本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存 ...

  2. C#中结构体定义并转换字节数组

    ref: https://www.cnblogs.com/dafanjoy/p/7818126.html C#中结构体定义并转换字节数组 最近的项目在做socket通信报文解析的时候,用到了结构体与字 ...

  3. c语言结构体struct所占字节数求解

    原本觉的c语言学的还不错,今天看了一下c语言的有关书籍,看到求结构体大小的例子,心想这不是很简单吗,不就是把所有成员的大小加起来就行了,其实远没我想的简单,看来c语言还要继续学习哈哈. 先看一个实例 ...

  4. 关于C语言中的结构体所占的字节数 sizeof(struct)

    C语言中的结构体所占的字节数 ,用sizeof求一个结构体的大小 C语言中用sizeof求结构体所占字节数的详细方法. 一.非嵌套结构体 struct one{char a; // 1(char所占字 ...

  5. C语言《认识结构体》---重点解析内存对齐

    文章目录 结构体 一.结构体概念 二.结构体声明 (1).特殊声明 三.结构体变量的定义和初始化 (1).定义初始化例子1 (2).定义初始化例子2: (3).结构嵌套 四.结构体自引用 (1). 结 ...

  6. 结构体、类的成员对齐

    自然对齐 为了保证CPU的运算稳定和效率,要求基本数据类型在内存中的存储地址必须自然对齐.所谓自然对齐,就是基本数据类型的变量不能简单的存储于内存中的任意地址处,它们的起始地址必须能够被它们的大小整除 ...

  7. 结构体在内存中的对齐规则

    一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和. 例一: #include <iostream> using namespace std; struct X { ...

  8. c语言结构体变量所占字节计算,【C语言】结构体占用字节数及存储与空间分配...

    我们都知道在数据类型中,char类型占1个字节,short占2个字节,int占4个字节,long占8个字节等等. 在计算结构体大小时需要考虑其内存布局,结构体在内存中存放是按单元存放的,每个单元多大取 ...

  9. 一文了解结构体字节对齐

    结构体字节对齐详解 表述如有不正确的地方,欢迎批评指正. C++/C 常见的基本数据类型: bool short (short int) int long (long int) long long ( ...

最新文章

  1. CUDA 8的混合精度编程
  2. 非线性回归模型java_R中的非线性多元回归
  3. 视频互动直播软件开发中的连麦问题分析
  4. Android自定义View研究(四) -- 在XML中定义View
  5. VTK:网格之AddCell
  6. 201110阶段二qt事件
  7. mybatis Example 使用方法
  8. 第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波18 - 低通、高通、带阻和带通滤波器、组合使用空间增强方法
  9. 良性计算机病毒对计算有没有危害机系统,154、计算机病毒有良性和恶性之分,其中, – 手机爱问...
  10. 乘方运算中的“次幂”和“次方”有什么区别?
  11. python程序设计题怎么写_《Python语言程序设计基础》第1章程序练习题
  12. Linux 中 elasticsearch6.3.0 单机安装
  13. 在C#中使用SQL语句什么情况需要使用‘单引号’和“双引号”
  14. 基于移动最小二乘的图像变形
  15. php递归函数名字,php递归示例 php递归函数代码
  16. MATLAB与STK互联18:卫星对象操作(9)—地面站可见性计算并获取数据2(补充上篇博文,有些问题需要澄清)
  17. 最好用的视频压缩软件压缩教程
  18. python面试整理
  19. 简述计算机五种常见动画及特点。【可拆成多个简答】
  20. 安卓中的对称加密,非对称加密,MD5加密的算法

热门文章

  1. 线上比赛中关于视觉AI组与信标组补充说明
  2. 用于计算无线充电中LCC补偿网络器件参数的小程序
  3. 怎么交换两个字符串_leetcode1202_go_交换字符串中的元素
  4. mysql innodb 数据复制_五千万的数据 复制到另张表 是先复制数据再加索引还是先建好索引再复制数据 表引擎Innodb...
  5. linux 脚本 ,shell中的与
  6. java float 加法_Java-杂项:Float 加减精度问题
  7. java非打印字符,使用Java正则表达式匹配不可打印字符
  8. java中文问号_java 中文转出来是问号怎么回事?有大神知道怎么改么?
  9. vue 心跳监控_【笔记】vue中websocket心跳机制
  10. 数字集成电路的层次关系