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

C++面试题之结构体内存对齐计算问题总结大全

这篇文章主要给大家总结了关于C++面试题中结构体内存对齐计算问题的相关资料,文中通过示例代码介绍的非常详细,通过这些介绍的内容对大家在面试C++工作的时候,会有一定的参考帮助,需要的朋友们下面随着小编来一起学习学习吧。

前言

本文给大家介绍的是关于C++结构体内存对齐计算的相关内容,内存对齐计算可谓是笔试题的必考题,但是如何按照计算原则算出正确答案一开始也不是很容易的事,所以专门通过例子来复习下关于结构体内存对齐的计算问题。话不多说,来一起看看详细介绍吧。

编译环境:vs2015

对齐原则:

      原则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

      原则2:结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

      原则3:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。

默认对齐值:

Linux 默认#pragma pack(4)

window 默认#pragma pack(8)

注:可以通过预编译命令#pragma pack(n) ,n=1,2,4,8,16来改变这一系数,其中的n就是指定的“对齐系数”。

例一:一字节对齐

第一步: 成员数据对齐

#pragma pack(1)
struct AA {
 int a; //长度4 <1 按1对齐;偏移量为0;存放位置区间[0,3]
 char b; //长度1 = 1 按1对齐;偏移量为4;存放位置区间[4]
 short c; //长度2 > 1 按1对齐;偏移量为5;存放位置区间[5,6]
 char d; //长度1 = 1 按1对齐;偏移量为6;存放位置区间[7]
 //整体存放在[0~7]位置区间中,共八个字节。
};
#pragma pack()

第二步: 整体对齐

整体对齐系数 = min((max(int,short,char), 1) = 1,所以不需要再进行整体对齐。整体大小就为8。

图示如下:

例二:二字节对齐

第一步: 成员数据对齐

#pragma pack(2)
struct AA {
 int a; //长度4 > 2 按2对齐;偏移量为0;存放位置区间[0,3]
 char b; //长度1 <2 按1对齐;偏移量为4;存放位置区间[4]
 short c; //长度2 = 2 按2对齐;偏移量要提升到2的倍数6;存放位置区间[6,7]
 char d; //长度1 <2 按1对齐;偏移量为7;存放位置区间[8];共九个字节
};
#pragma pack()

第二步: 整体对齐

整体对齐系数 = min((max(int,short,char), 2) = 2,将9提升到2的倍数,则为10.所以最终结果为10个字节。

图示如下:(X为补齐部分)

例三:四字节对齐

第一步: 成员数据对齐

#pragma pack(4)
struct AA {
 int a; //长度4 = 4 按4对齐;偏移量为0;存放位置区间[0,3]
 char b; //长度1 <4 按1对齐;偏移量为4;存放位置区间[4]
 short c; //长度2 <4 按2对齐;偏移量要提升到2的倍数6;存放位置区间[6,7]
 char d; //长度1 <4 按1对齐;偏移量为7;存放位置区间[8];总大小为9
};
#pragma pack()

第二步: 整体对齐

整体对齐系数 = min((max(int,short,char), 4) = 4,将9提升到4的倍数,则为12.所以最终结果为12个字节。

图示如下:(X为补齐部分)

例三:八字节对齐

第一步: 成员数据对齐

#pragma pack(8)
struct AA {
 int a; //长度4 <8 按4对齐;偏移量为0;存放位置区间[0,3]
 char b; //长度1 <8 按1对齐;偏移量为4;存放位置区间[4]
 short c; //长度2 <8 按2对齐;偏移量要提升到2的倍数6;存放位置区间[6,7]
 char d; //长度1 <8 按1对齐;偏移量为7;存放位置区间[8],总大小为9
};
#pragma pack()

第二步: 整体对齐

整体对齐系数 = min((max(int,short,char), 8) = 4,将9提升到4的倍数,则为12.所以最终结果为12个字节。图示如上。

注:可以通过stddef.h库中的offsetof宏来查看对应结构体元素的偏移量。

例四:结构体中包含结构体的运算

整体计算过程如下

struct EE
{
 int a; //长度4 <8 按4对齐;偏移量为0;存放位置区间[0,3]
 char b; //长度1 <8 按1对齐;偏移量为4;存放位置区间[4]
 short c; //长度2 <8 按2对齐;偏移量由5提升到6;存放位置区间[6,7]
 //结构体内部最大元素为int,由于偏移量为8刚好是4的整数倍,所以从8开始存放接下来的struct FF
 struct FF
 {
 int a1; //长度4 <8 按4对齐;偏移量为8;存放位置区间[8,11]
 char b1; //长度1 <8 按1对齐;偏移量为12;存放位置区间[12]
 short c1; //长度2 <8 按2对齐;偏移量为13,提升到2的倍数14;存放位置区间[14,15]
 char d1; //长度1 <8 按1对齐;偏移量为16;存放位置区间[16]
 };
 //整体对齐系数 = min((max(int,short,char), 8) = 4,将内存大小由17补齐到4的整数倍20
 char d;  //长度1 <8 按1对齐;偏移量为21;存放位置区间[21]
 //整体对齐系数 = min((max(int,short,char), 8) = 4,将内存大小由21补齐到4的整数倍24
};

图示如下:

例五:再来一个嵌套结构体的计算

整体计算过程如下

struct B {
 char e[2]; //长度1 <8 按2对齐;偏移量为0;存放位置区间[0,1]
 short h; //长度2 <8 按2对齐;偏移量为2;存放位置区间[2,3]
 //结构体内部最大元素为double,偏移量为4,提升到8,所以从8开始存放接下来的struct A
 struct A {
 int a; //长度4 <8 按4对齐;偏移量为8;存放位置区间[8,11]
 double b; //长度8 = 8 按8对齐;偏移量为12,提升到16;存放位置区间16,23]
 float c; //长度4 <8,按4对齐;偏移量为24,存放位置区间[24,27]
 };
 //整体对齐系数 = min((max(int,double,float), 8) = 8,将内存大小由28补齐到8的整数倍32
};

图示如下:

小结:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


推荐阅读
  • 本文详细介绍如何使用arm-eabi-gdb调试Android平台上的C/C++程序。通过具体步骤和实用技巧,帮助开发者更高效地进行调试工作。 ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 掌握Linux:基础命令入门
    本章节深入浅出地介绍了Linux系统中的基本命令操作,帮助读者快速上手并理解其核心功能。 ... [详细]
  • 解决Linux系统中pygraphviz安装问题
    本文探讨了在Linux环境下安装pygraphviz时遇到的常见问题,并提供了详细的解决方案和最佳实践。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 在哈佛大学商学院举行的Cyberposium大会上,专家们深入探讨了开源软件的崛起及其对企业市场的影响。会议指出,开源软件不仅为企业提供了新的增长机会,还促进了软件质量的提升和创新。 ... [详细]
  • CMake跨平台开发实践
    本文介绍如何使用CMake支持不同平台的代码编译。通过一个简单的示例,我们将展示如何编写CMakeLists.txt以适应Linux和Windows平台,并实现跨平台的函数调用。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 如何配置Unturned服务器及其消息设置
    本文详细介绍了Unturned服务器的配置方法和消息设置技巧,帮助用户了解并优化服务器管理。同时,提供了关于云服务资源操作记录、远程登录设置以及文件传输的相关补充信息。 ... [详细]
  • 在Ubuntu 16.04 LTS上配置Qt Creator开发环境
    本文详细介绍了如何在Ubuntu 16.04 LTS系统中安装和配置Qt Creator,涵盖了从下载到安装的全过程,并提供了常见问题的解决方案。 ... [详细]
  • 本文深入探讨了Linux系统中网卡绑定(bonding)的七种工作模式。网卡绑定技术通过将多个物理网卡组合成一个逻辑网卡,实现网络冗余、带宽聚合和负载均衡,在生产环境中广泛应用。文章详细介绍了每种模式的特点、适用场景及配置方法。 ... [详细]
author-avatar
孙亦然5277
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有