C语言结构体的字节对齐

news2024/11/24 12:45:50

C语言结构体的字节对齐

什么是字节对齐

首先来看下面的程序:

#include <stdio.h>

typedef struct n1{
    int a;
    char b;
    char c; 
} N_stru1;

typedef struct n2{
    char b;
    int a;
    char c;
} N_stru2;

int main() {
    N_stru1 n1;
    N_stru2 n2;
    printf("%d\n", sizeof(n1));
    printf("%d\n", sizeof(n2));
    return 0;
}

两个输出的结果是什么?

如图:
在这里插入图片描述
明明结构体中的成员类型数量都是一样的,为什么会出现存储他们的结构体大小不一样的情况呢?

原因是这样的,下面是这两个结构体在内存中的存储结构:

n1:

地址0x000x010x020x030x040x050x060x07
内容a---bc//

n2:

地址0x000x010x020x030x040x050x060x070x080x090x100x11
内容b///a---c///

ps:在上面的表格中,“-”表示被使用,“/”表示被空置或者跳过

通过观察表格会发现:n2这个结构体中的字节有很多的空间被浪费了(因为有更多空置的内存),所以可以得出一个结论:

C语言的编译器在给结构体分配空间时按照结构体成员的声明顺序分配,并且其空间遵循内存边界要求最严格的成员的空间大小分配空间

如果你已经明白,那么可以跳过下面这个小板块的内容,如果还是没有,我讲配合上面的例子进行说明:


编译器对于结构体成员分配结论的详细解释

上面的结论有两点:

  • 分配空间时按照结构体成员的声明顺序分配
  • 遵循内存边界要求最严格的成员的空间大小分配空间

第一点,观察上表:
可以发现n1中的成员从地址最低位向最高位依次是:a、b、c
而n2中的成员从地址最低位向最高位依次是:b、a、c

这个顺序和我们在程序中对结构体成员的声明顺序是相同的。

第二点:
在这个例子中,发现n1和n2的大小分别是8和12,他们都是4的倍数。
为什么要说是4的倍数呢?
因为在结构体成员中,所需空间最大的变量就是int类型,也就是4个字节,所以在这个例子中,4就是内存边界要求最严格的成员变量。
那么比4小的1个字节是不能构成分配空间的单位的,所以说,编译器会在不足边界要求的成员的内存分配中给他们填充一些空的空间,以达到最低要求。
所以在上面的例子中:
n1:

地址0x000x010x020x030x040x050x060x07
内容a---bc//

a是int类型,占4个字节,系统直接分配,
b是char类型,占1个字节,不足4字节,系统需要填充三个字节
c也是char类型,占1个字节,不足4字节,但由于前面有空的字节,所以直接放在空字节中,不再分配空间

n2:

地址0x000x010x020x030x040x050x060x070x080x090x100x11
内容b///a---c///

按顺序首先分配b,是char类型,不足4,填充3个字节
然后是a,满足4,不做处理直接分配
最后是c,不足4,前面字节已经被占用,因此再填充3个字节,分配

以上是对于结论的详细描述,不懂的可以在评论区提问。


那回到正题,什么是字节对齐呢?

下面是字节对齐的几个原则:

  • 结构体的自身对齐值是其成员中自身对齐值最大的那个值,或者是指定对齐值(如果有的话)。
  • 结构体的大小必须是其自身对齐值的整数倍,如果不足则补齐。
  • 结构体的每个成员必须放在其自身对齐值的整数倍的地址上,如果不够则空出一些字节。

很多文章没有提到“对齐”这个概念,这里特别做一下解释:
“成员的空间分配 遵循内存边界要求最严格的成员的空间大小 分配空间”
其实就是上文中结论的后半部分

这里不再对64位和32位的系统进行比较,他们都遵循上述规则。

为什么要字节对齐

首先要明确的一点就是:CPU在内存中的取值是怎么样的。

操作系统位数与信息处理

显然,如果你的电脑是64位,那么CPU最大可以一次取64位(64bit换算成字节是8字节)宽的值(在内存中),然后对他们进行处理,这意味着:系统的操作位数越高,电脑运行速度会更快,处理多信息的能力就越强。

CPU读取数据的格式

CPU在访问内存时,通常是以一个字为单位,而一个字的长度就取决于CPU的位数。在64位操作系统中,一个字通常是8字节。那么一次性在内存中可以读取的字节大小就是8个字节,很舒服的是,在x86系统架构中,内存中一个内存块(也叫缓存行)的大小就是8个字节,这也恰恰是编译器在系统中开辟内存的单位,CPU一次性就可以读取这个内存块中的所有内容。

这个和字节对齐有什么关系呢?

现在来想一个问题:假设你正在给内存分配变量空间,现在已经分配到内存块的最后一个字节了(也就是说,这个内存块前面的内容已经被其他变量占用了,8字节的内存块只有1个字节是空闲的),此时你要分配一个4字节整形变量,那么你选择以下哪种分配方式?

  • 从这个内存块最后剩下的1个字节开始分配一部分,然后再把剩下的一部分放在新的内存块中
  • 直接丢弃空余的1字节,直接把这个变量放在新的内存块中。

仔细看过上面的文章的人应该都会选择第二个选项,因为这样可以减少CPU读取数据的次数。

字节对齐的意义
这就是字节对齐的意义,如果你字节对齐,你会发现,在C语言中,无论你怎么访问变量(除非这个变量大于内存块的大小),访问次数永远都是1次!!!不会出现CPU读取两次内存的情况!!!这样一来大大的提高了内存访问的速度

如何用利用系统字节对齐的特性提高自己的编程水平?

很简单,根据上面的例子就可以看出,当在结构体中声明变量的时候,我们应该尽量做到以下几点:

  • 相同的数据类型放在一起
  • 数据类型大的变量放在声明顺序之前
  • 尽量的声明4的整数倍大小的空间(哪怕多声明的变量没有用)

对于最后一点,解释是这样的:

如果你声明了一个三个字节大小的空间(short是2个字节,加上1个char类型是三个字节),那么在字节对齐的影响下,最后一个字节就不能使用了,这块空间没有任何用,你为什么不多开辟一个变量,说不定未来能用上呢?


以上就是C语言结构体字节对齐的所有内容,创作不易!!
欢迎读者评论提问、点赞、关注!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1372924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

查看SOLIDWORKS 2024的最佳价格和特惠优惠

尊敬的客户&#xff0c; 在 SOLIDWORKS 2024 引领设计技术的未来之际&#xff0c;我们为您提供了更划算的价格和特惠优惠&#xff0c;助您在设计领域更进一步。本文将为您介绍 SOLIDWORKS 2024 的最佳价格&#xff0c;确保您获得最佳的设计工具和投资回报。 1. SOLIDWORKS202…

鸿蒙 command not found: ohpm

第一步&#xff1a;找到ohpm home copy路径&#xff1a;/Users/admin/newohpm 第二步&#xff1a;打开终端 输入&#xff1a;open ~/.bash_profile 会弹出 第三步&#xff1a;弹框中输入&#xff1a; export OHPM_HOME/Users/admin/newohpm export PATH${PATH}:${OHPM_HOM…

使用rembg库提取图像前景(移除图像背景),并构建web应用

1、图像中的前景与背景 在深度学习图像处理领域中&#xff0c;图像内容可以被定义为前景与背景两部分&#xff0c;其中感兴趣图形的被定义为前景&#xff0c;不感兴趣区域的背景。如在目标检测中&#xff0c;被框出来的目标则被定义为前景。此外&#xff0c;前景识别也可以理解…

element plus el-form双列布局及拓展任意布局

1 场景 一般表单我们直接默认布局&#xff0c;也就是单列布局&#xff0c;突然有个人员信息表单&#xff0c;需要双列布局的需求&#xff0c;简单实现并拓展下 2 思路 直接无脑divflex布局实现 3 代码 <template><el-form ref"formRef" :model"fo…

【Mysql】InnoDB 引擎中的页目录

一、页目录和槽 现在知道记录在页中按照主键大小顺序串成了单链表。 那么我使用主键查询的时候&#xff0c;最顺其自然的办法肯定是从第一条记录&#xff0c;也就是 Infrimum 记录开始&#xff0c;一直向后找&#xff0c;只要存在总会找到。这种在数据量少的时候还好说&#x…

Federated Unlearning for On-Device Recommendation

WSDM 2023 CCF-B Federated Unlearning for On-Device Recommendation 本文工作的主要介绍 本文主要介绍了一种名为FRU&#xff08;Federated Recommendation Unlearning&#xff09;的联邦学习框架&#xff0c;用于在设备端的推荐系统中实现用户数据的有效擦除和模型重建。…

Web 缓存代理—— Nginx、CDN

代理的工作机制 代替客户机向网站请求数据&#xff0c;从而可以隐藏用户的真实IP地址。将获得的网页数据&#xff08;静态 Web 元素&#xff09;保存到缓存中并发送给客户机&#xff0c;以便下次请求相同的数据时快速响应。 代理服务器的概念 代理服务器是一个位于客户端和原始…

Kafka之集群搭建

1. 为什么要使用kafka集群 单机服务下&#xff0c;Kafka已经具备了非常高的性能。TPS能够达到百万级别。但是&#xff0c;在实际工作中使用时&#xff0c;单机搭建的Kafka会有很大的局限性。 ​ 消息太多&#xff0c;需要分开保存。Kafka是面向海量消息设计的&#xff0c;一个T…

徐怀钰巡演将开启,巡回22城上演全民金曲盛宴

1月10日下午&#xff0c;天后徐怀钰空降成都&#xff0c;现身“徐怀钰2024倒数3秒巡回演唱会”新闻发布会&#xff0c;在行业大咖、百余名歌迷的陪伴与在线数万直播观众的见证下&#xff0c;正式揭晓22座巡演城市&#xff0c;宣告巡演璀璨开启。主办方今夕何夕文化表示&#xf…

系列十、Java中的八种基本数据类型

一、Java中的八种基本数据类型 1.1、概览 1.2、备注 byte最大值&#xff1a;127 ,byte最小值&#xff1a;-128 short最大值&#xff1a;32767 ,short最小值&#xff1a;-32768 int最大值&#xff1a;2147483647 ,int最小值&#xff1a;-2147483648 long最大值&#xff1a;9…

云上攻防--云原生Docker逃逸--特权逃逸--危险挂载--漏洞逃逸

云上攻防–云原生&&Docker逃逸–特权逃逸–危险挂载–漏洞逃逸 目录标题 云上攻防--云原生&&Docker逃逸--特权逃逸--危险挂载--漏洞逃逸Docker介绍判断Docker环境容器逃逸-特权模式容器逃逸-危险挂载挂载DockerSocket逃逸挂载宿主机procfs逃逸 容器逃逸-Docker…

【前端素材】bootstrap4实现在线蛋糕甜品店网页Tehzeeb

一、需求分析 在线蛋糕甜品店的网站通常包含以下几个方面的内容和功能&#xff1a; 主页&#xff1a;网站的主页是用户进入网站的第一个页面&#xff0c;通常会展示一些精选蛋糕和甜品的图片和介绍&#xff0c;以吸引用户的注意力。主页还可能包含一些特别促销或最新的产品信息…

Matlab 分段函数(piecewise)

语法 pw piecewise(cond1,val1,cond2,val2,...) pw piecewise(cond1,val1,cond2,val2,...,otherwiseVal)描述 pw piecewise(cond1,val1,cond2,val2,...) 返回分段表达式或函数pw&#xff0c;当cond1为True时&#xff0c;其值为val1&#xff0c;当cond2为True时&#xff0…

超维空间M1无人机使用说明书——61、ROS无人机yolo识别与投放

引言&#xff1a;使用yolo进行物体识别&#xff0c;根据返回的目标位置信息&#xff0c;控制无人机全向移动&#xff0c;当无人机到达目标物的正上方&#xff0c;满足一定的误差阈值后&#xff0c;ROS发布控制控制将舵机挂载的物体抛下&#xff0c;紧接着无人机前往起飞点上方寻…

Java中异常处理-详解

异常&#xff08;Exception&#xff09; JVM 默认处理方案 把异常的名称&#xff0c;异常的原因&#xff0c;及异常出错的位置等信息输出在控制台程序停止执行 异常类型 编译时异常必须显示处理&#xff0c;否则程序会发生错误&#xff0c;无法通过编译运行时异常无需显示处理…

灵活实现主题切换 —— 白天、黑夜等主题

1、上代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><style>/* 默认的CSS变量集合 */:root {--pr…

光伏方案设计有什么注意点?

光伏方案设计是实现光伏发电系统高效运行的关键环节。在进行光伏方案设计时&#xff0c;有几个重要的注意点需要特别关注。 首先&#xff0c;要充分考虑地理位置和气候条件。不同地区的日照时数、太阳辐射强度和日照角度都有所不同&#xff0c;这些因素直接影响光伏发电系统的发…

85.乐理基础-记号篇-力度记号

内容来源于&#xff1a;三分钟音乐社 上一个内容&#xff1a;78.乐理基础-非常见拍号如何打拍子-CSDN博客 85-78之间的内容观看索引&#xff1a; 腾讯课堂-三分钟音乐社-打拍子&#xff08;20&#xff09;-总结、重点、练习与检验方法开始看 力度记号&#xff1a;p、f、mp、…

网络协议攻击与模拟_02ARP协议

一、arp协议简介 一个工作在二层的三层协议&#xff0c;事一个2.5层协议 ARP协议地址解析协议&#xff0c;将一个已知的Ip地址解析为MAC地址&#xff0c;从而进行二层数据交互 二、工作流程 1、两个阶段 ARP请求ARP响应 两台主机IP地址主机A和主机B&#xff0c;IP地址和MAC…

2024年AI红利:抓住AI内容写作、绘画、数字人、等四大变现机遇

2023年见证了人工智能大模型的爆发&#xff0c;其影响力超出了科技界范畴&#xff0c;成为推动社会进步的重要力量。大模型的突破性进展引起了全球关注&#xff0c;被视为科技发展4.0时代的革命性创新。而每一次革命性创新都是一把双刃剑&#xff0c;随之而来的互联网大裁员事件…