热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c++基础知识(六)结构体字节对齐

我们在使用结构体的时候,有没有发现这样的情况,用sizeof(结构体)算出来的内存字节数与结构体里面的数据所占内存字节数总和不匹配。比如以下:

我们在使用结构体的时候,有没有发现这样的情况,用sizeof(结构体)算出来的内存字节数与结构体里面的数据所占内存字节数总和不匹配。

比如以下:

struct A
{
char a='0';//占用1个字节
int b=0;//占用4个字节
short c=0;//占用2个字节
};
本来总共应该是7个字节
但是用sizeof(结构体)算出来却是12个字节

今天我们来看看到底是怎么回事呢?原来啊,是编译器帮我们做了字节对齐。做字节对齐的目的是提高内存的访问效率。

比如32位CPU,每个总线周期都是偶数的地址开始访问读取32位的数据,但是如果数据不是按从偶数开始放置的,则读取则需要两个总线周期才能读到想要的数据。因此需要在内存存放数据时做内存对齐。

内存对齐需要遵守两个基本原则:

1、对于结构体的成员,第一个数据偏移地址为0,后面的数据的偏移量需要是其所占内存大小的整数倍。否则的话就需要进行填充字节数。

    举栗子:

    比如结构体A,很明显第一个成员为a,所以它的偏移地址为0,按照该原则,b占用是4个字节,所以b相对于a的偏移地址必须是4个整数倍,则最小为4,因为a占用1个字节,所以需要在a,b之间填充3个字节来进行字节内存对齐。同理,b的便宜地址变为了4,b本身占4个字节。b的地址为4----8,c的偏移地址就为8,本身占2个字节,偏移量是所占大小的4倍,不需要填充。

2、结构体所有数据内存对齐后,但是结构体也需要内存对齐,其整个结构体内存大小必须是结构体内中数据所占内存最大的整数倍。

   同样看结构体A,从1中我们知道a,b之间填充了3个字节,bc没有填充,总共占据了1+3+4+2=10个字节。根据原则2,结构体大小必须为4(因为该结构体数据中最大占4个字节)倍数,所以末尾再填充两个字节,总共是12个字节。

3、如果程序中有#pragma pack(n) 预编译指令,则所有成员对齐以n字节为准(即偏移量为N的整数倍),不在考虑当前类型以及最大结构体类型。



推荐阅读
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
author-avatar
沉睡森林
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有