热门标签 | HotTags
当前位置:  开发笔记 > IOS > 正文

C++中的数据对齐示例详解

这篇文章主要介绍了C++中数据对齐的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

对于C/C++程序员来说,掌握数据对齐是很有必要的,因为只有了解了这个概念,才能知道编译器在什么时候会偷偷的塞入一些字节(padding)到我们的结构体(struct/class),也唯有这样我们才能更好的理解、优化结构体和内存。

几个栗子

看看几个简单的Struct,能猜出他们的SIZE吗?(运行于64Bit win10 vs2017)

struct A
{
	char c1;
};

struct B
{
	int i1;
};

struct C
{
	char c1;
	int i1;
};

struct D
{
	char c1;
	int i1;
	char c2;
};

struct E
{
	char c1;
	char c2;
	int i1;
};

int main()
{
	std::cout <<"A's size is " <

先揭晓答案

如果对任何一个结构体的大小有疑问,那么这篇文章非常适合你,请接着往下看,我们会解释数据对齐。

数据对齐

处理器读取数据的行为

在C/C++中,每种数据类型都有对齐的要求(这个更多是处理器的要求而非语言层面),大家都知道,处理器工作的时候需要数据总线(data bus)、控制总线(control bus)和地址总线(address bus)一起配合工作。而在数据总线取数据的时候,处理器为了高效的工作,一次会取4byte或者8byte数据(依系统32bit或者64bit而不同),这就是所谓数据字长(word size)。同时在读取内存的时候,也会从4byte或者8byte边界开始读取,这是处理器行为,我们只能尊重不能改变。考虑下面的例子,

struct F
{
  int i1
  char c1;
  int i2;
  char c2;
};
#include 

int main()
{
  F f;
  printf("0x%p\n", &f);
}

它的起始地址输出是:

0x000000FE8BCFFB88

所以在内存中可能的排列就是:

读取数据的时候,每次读入8btye,8个字节为一个读取单元,就像蒸笼的一格,这样做的好处是每次可以尽可能多的读入数据,减少读取次数。设想,如果一次只读入一个字节数据,那么一个Int就需要4次读取,明显效率就很低。

编译器的做法

如果没有对齐

了解了处理器如何读取数据的,我们就不难理解编译器为什么会做出调整。试想,如果编译器不在后台做出填充(padding),那么我们就会遇到这种情况

像这样的话,访问i1, c1 都不会有问题,但是访问i2就会发现,数据散落在不同的蒸笼,原本只需要一次读取就行的数据,还需要一次额外的数据读取才行,这就造成了读取数据的低效,在某些严格的CPU,比如ARM上面,这种非对齐的数据读操作甚至会被拒绝。

编译器对齐

所以,为了让数据读取效率最大化,编译器会选择牺牲一部分空间来换取效率,他们不会允许i2横跨两个读取单元。在实际中,上面的结构体会是这样的

可以看出,

  • 为了解决i2的对齐问题,c1之后填充了3个空字节
  • 同时为了保持整个结构体的对齐(结构体对齐字节数等于其最大的数据成员的对齐字节数,这里是4),在结构体的尾部还会有3个空字节
  • 整个结构体的大小就是16字节,有6个字节是空字节。

所以,在编译器的作用下,最开始几个Struct实际上扩展为,

struct A
{
	char c1; //no padding
};

struct B
{
	int i1; //no padding
};

struct C
{
	char c1;
	char pad[3]; //padding
	int i1;
};

struct D
{
	char c1;
	char pad1[3]; //padding
	int i1;
	char c2;
	char pad2[3]; //padding
};

struct E
{
	char c1;
	char c2;
	char pad[2]; //padding
	int i1;
};

对齐的目的是要让数据访问更高效,一般来说,数据类型的对齐要求和它的长度是一致的,比如,

  • char 是 1
  • short 是 2
  • int 是 4
  • double 是 8

这不是巧合,比如short,2对齐保证了short只可能出现在一个读取单元的0, 2, 4, 6格,而不会出现在1, 3, 5, 7格;再比如int,4对齐保证了一个读取单元可以装载2个int——在0或者4格。从根本上杜绝了同一个数据横跨读取单元的问题。

总结

可能有人会疑惑了,知道这些对我们工作有什么帮助吗?如果仅仅是比较High-Level的应用程序编程,可能确实感觉不明显,最多就当成一个知识点了解一下,但是对于搞比较底层开发的,比如游戏引擎,或者是在内存环境很紧张的情况下开发,比如嵌入式开发,那了解这个有助于在某些情况下节约内存。

考虑前面的D和E结构体,他们拥有完全一样的成员,却有着不同的结构体大小,就是因为E选择把对齐要求接近的变量类型放在一起,减小了填充padding的数量从而达到了减小结构体大小的目的。

在设计结构体的时候,这个可以作为一个考量,有一些函数可以帮助我们查看某个类型的对齐要求,比如Visual Studio中的__alignof函数。

这就是关于数据对齐的一些基础知识,希望能帮助大家解惑,如果您发现本文有任何写的不对的地方,欢迎留言指出来;如果有其他问题,也欢迎留言一起讨论。

到此这篇关于C++中的数据对齐的文章就介绍到这了,更多相关C++数据对齐内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 在Kubernetes集群中部署Kuboard
    本文详细介绍了如何在Kubernetes(简称k8s)环境中部署Kuboard,包括必要的命令和步骤,帮助用户顺利完成安装。 ... [详细]
  • http:acm.hdu.edu.cnshowproblem.php?pid1846好几天没出题了,今天终于水了一题巴什博弈题。总结:【一】巴什博弈对象:一堆石子(可延伸 ... [详细]
  • 本文介绍了如何使用命令行在 Windows 系统中启动或关闭 VMWare 的关键服务,包括 VMwareHostd、VMAuthdService、VMUSBArbService、VMware NAT Service 和 VMnetDHCP。 ... [详细]
  • 本文介绍并分享了三个个人开源项目,涵盖单元测试中HttpContext的可测试性增强、Visual Studio插件开发以及单元测试报告自动生成工具。 ... [详细]
  • 本文详细探讨了C++中赋值运算符重载函数(operator=)的使用方法和注意事项,结合实例分析了其参数、返回值、调用时机等关键点,并讨论了浅拷贝和深拷贝的区别及其重要性。 ... [详细]
  • 题意题目大意很简单,很容易找出对应字母的ASCII码值的关系,但是有一点需要注意,请看代码:读字符串必须要用getline ... [详细]
  • 在该问题中,若存在一个节点x满足特定条件,则x所在的强连通分量(SCC)同样满足条件。合法的SCC数量最多为1,因为多个SCC之间具有传递性,理论上应能合并。本文将通过拓扑排序和缩点技术来探讨这一算法的实现。 ... [详细]
  • 本文提供了详细的步骤,介绍如何将基于Maven的Java EE项目从Eclipse IDE部署到JBoss应用服务器上。适合初学者和中级开发者参考。 ... [详细]
  • 近期遇到 M1 Mac Mini 在休眠状态下频繁自动重启的问题,通过日志分析尝试找出可能的原因。 ... [详细]
  • 前文|功能型_品读鸿蒙HDF架构
    前文|功能型_品读鸿蒙HDF架构 ... [详细]
  • 尽管PHP是一种强大且灵活的Web开发语言,但开发者在使用过程中常会陷入一些典型的陷阱。本文旨在列出PHP开发中最为常见的10种错误,并提供相应的预防建议。 ... [详细]
  • KVO(键值观察)是iOS开发中的一项重要技术,它允许一个对象监视另一个对象的属性变化,并在这些属性发生变化时得到通知。KVO特别适用于需要响应模型数据变化的场景。 ... [详细]
  • 题目描述了一个病毒检测问题,要求使用AC自动机算法统计目标文本中多个模式串的出现次数。 ... [详细]
  • 本文旨在介绍在iOS平台进行直播技术开发前的准备工作,重点讲解AVFoundation框架的基本概念和使用方法。通过对AVFoundation的深入理解,开发者能够更好地掌握直播应用中的音视频处理技巧。 ... [详细]
  • 如何在Android和iOS上捕获应用程序崩溃的日志
    本文详细介绍了如何在Android和iOS设备上收集应用崩溃时的日志,包括所需的工具、步骤以及一些常见的注意事项。 ... [详细]
author-avatar
兰陵殇lu_734_168
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有