如何计算结构体变量的大小(结构体内存对齐)

news2024/10/25 12:15:58

   

目录

一、对齐规则

二、结构体大小计算三步曲

第一步:确定对齐数

第二步:根据对齐数确定每个成员相对位置

第三步:通过最大对齐数来确定结构体最终大小

三、内存浪费

四、为什么要存在内存对齐


    在C语言中,变量由于类型不同在内存中开辟空间的大小不同,而结构体类型是一种特殊的变量类型,其可以是多个类型的集合,甚至结构体嵌结构体类型,那么结构体类型变量占内存空间的大小该如何计算呢?这也是一个特别热门的考点。

一、对齐规则

1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处。


2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
        对齐数 = 编译器默认的一个对齐数与该成员变量大小的较小值
        VS 中默认的值为 8 
        Linux中gcc没有默认对齐数,对齐数就是成员自身的大小


3.结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的
整数倍


4.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构
体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

二、结构体大小计算三步曲

我们由此结构体举例说明(vs环境):

struct S3
{
    char c;
    double d;
    int i;
};

第一步:确定对齐数

找出每个成员变量的大小将其与编译器的默认对齐数相比较,取其较小值为该成员变量的对齐数。

第二步:根据对齐数确定每个成员相对位置

结构体变量地址为零下标,结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处,其他成员变量要对齐到对齐的整数倍的地址处。

第三步:通过最大对齐数来确定结构体最终大小

结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的
整数倍。

看上图:紫色部分(double d成员占用)+红色部分(char c成员占用)+绿色部分(int i成员占用)+红色与紫色之间的白色部分总共占用了20个字节的内存空间。而20并非最大对齐数8的整数倍,那么取8大于20的最小整数倍24为结构体最终大小。

三、内存浪费

        由于对齐规则的存在,导致结构体虽然成员变量相同,但很可能会出现结构体大小不同的情况造成内存浪费。

        我们可以在构建结构体时,将每个成员变量的间隙在保证符合对齐规则的情况下尽量减小,这是一种合理且推荐使用的方法。

        当然也可以使用#pragma pack( )的预处理来修改默认对齐数以达到减小空隙的效果,但是不推荐。详细见:C语言中#pragma pack(1)的用法_#pack(1)-CSDN博客

#include <stdio.h>

#pragma pack(4)//设置默认对齐数为4
struct S1
{
	double a;//8/4->4
	int b;//4/4->4
	char c;//1/4->1
};//12
#pragma pack()//取消设置的默认对齐数,还原为默认

#pragma pack(1)//设置默认对齐数为1
struct S2
{
	char a;//1/1->1
	int b;//4/1->1
	char c;//1/1->1
};//6
#pragma pack()//取消设置的默认对齐数,还原为默认

int main()
{
	printf("%d\n", sizeof(struct S1));//打印结果为16
	printf("%d\n", sizeof(struct S2));//打印结果为6
	return 0;
}

四、为什么要存在内存对齐

1. 平台原因(移植原因):
        不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。


2. 性能原因:
        数据结构(尤其是栈)应该尽可能地在自然然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。假设一个处理器总是从内存中取8个字节,则地址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读或者写值了。否则,我们可能需要执行两次内存访问,因为对象可能被分放在两个8字节内存块中。


总体来说:结构体的内存对齐是拿空间来换取时间的做法


 

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

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

相关文章

由于“xinput1_3.dll缺失“而导致的错误有哪些解决办?分享几种修复xinput1_3.dll丢失的方法

当您尝试运行某些游戏或程序时&#xff0c;可能会遇到由于"xinput1_3.dll缺失"而导致的错误。这个DLL文件是MicrosoftDirectX的一部分&#xff0c;用于处理游戏中的输入设备&#xff0c;如操纵杆和游戏手柄。下面我们将探讨为何电脑会缺少xinput1_3.dll文件&#xff…

深度学习算法informer(时序预测)(四)(Decoder)

一、DecoderLayer架构如图&#xff08;不改变输入形状&#xff09; 二、Decoder整体 包括两部分 1. 多层DecoderLayer 2. 层归一化 代码如下 class DecoderLayer(nn.Module):def __init__(self, self_attention, cross_attention, d_model, d_ffNone,dropout0.1, activati…

阿里云 hpc8ae 实例商业化发布详解

云布道师 引言&#xff1a;本文整理自阿里云高性能计算产品负责人黄泽辉在【HPC 优化实例商业化发布会】中的分享。 近日&#xff0c;全球领先的云计算厂商阿里云宣布最新 HPC 优化实例 hpc8ae 的正式商业化&#xff0c;该实例依托阿里云自研的「飞天CIPU」架构体系&#xff…

java后端方法地址组成解析

本篇文章旨在记录后端方法被调用时&#xff0c;是如何组成的&#xff0c;以及组成的部分。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、后端方法地址是什么&#xff1f; 示例&#xff1a;http://127.0.0.1:8080/user/info 如果携带了路径参数…

RTX5全家桶源码综合模板发布,含FreeRTOS内核版本,将其打造成直接面向实际项目应用的综合框架(2024-06-19)

【说明】 1、RTX5全家桶的优势就是简单易用&#xff0c;初学的话&#xff0c;上手很快&#xff0c;稳定性也是杠杠的&#xff0c;且容易做稳定。 2、同时RTX5也是有汽车级&#xff0c;工业级&#xff0c;医疗和铁路安全认证&#xff0c;只是安全级别比ThreadX要稍微低些。 3…

数据量大、类型多!数据资产管理如何确保安全合规“不掉队”?

随着数字化进程加速与企业业务不断扩展&#xff0c;数据量呈爆炸式增长&#xff0c;数据类型也变得日益多样。大规模的数据积累在为企业带来丰富的信息资源&#xff0c;推动业务创新发展的同时&#xff0c;也为企业数据资产管理带来多方影响。 在政策引导和市场推动下&#xff…

Covalent实现对1000亿笔链上交易解析,支持AI长期数据可用性

在区块链与人工智能&#xff08;AI&#xff09;交汇处&#xff0c;讨论往往集中于去中心化推理和去中心化训练等方面。然而&#xff0c;这一数据的关键组成部分却一直未得到足够的重视。一个主要问题是&#xff1a;我们如何保护 AI 模型中的数据不受偏见和操纵的影响&#xff1…

网管工作实践_02_IP/MAC地址管理工具

1、ipconfig命令格式及参数 ipconfig是内置于Windows的TCP/IP应用程序&#xff0c;用于显示本地计算机网络适配器的MAC地址和IP地址等配置信息&#xff0c;这些信息一般用来榆验手动配置的TCP/IP设置是否正确。当在网络中使用 DHCP服务时&#xff0c;IPConfig可以检测计算机中分…

【阿里云服务器】【弹性云服务ECS】通过ssh登录远程服务器

一、操作系统 使用Windows11主机上的Ubuntu子系统&#xff0c;如下图所示&#xff1a; 二、云服务器登录方法 需知道&#xff1a;服务器ip地址、登录名和自己设置的登录密码&#xff1a; 上述系统用户名为root&#xff0c;需要在Ubuntu子系统中同样切换至root用户&#xff…

php 做一个文件下载服务器,得避免跨路径工具,安全很重要

任务 当使用PHP编写一个文件下载服务器时&#xff0c;安全性是非常重要的。以下是一些基本的步骤和最佳实践&#xff0c;以确保您的文件下载服务器是安全的&#xff0c;并且与CDN加速友好&#xff1a; 文章目录 任务基本要求&#xff1a;Nginx如何配置使用X-Sendfile或X-Acce…

推动 AI/ML 创新:使用 MinIO 的高性能对象存储构建特征存储

MinIO 为全球 S3 和对象存储设定了标准&#xff0c;并已成为实现 AI 代理和功能存储集成的关键参与者。随着组织努力利用 AI 的力量来推动创新并获得竞争优势&#xff0c;高效数据管理的重要性以及将 AI 代理无缝集成到现有工作流程中的能力变得至关重要。在本文中&#xff0c;…

RabbitMQ的简单使用 —— Python篇

&#xff08;一&#xff09;RabbitMQ的简介 RabbitMq 是实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息代理中间件。消息队列是一种应用程序对应用程序的通行方式&#xff0c;应用程序通过写消息&#xff0c;将消息传递于队列&#xff0c;由另一应用程序读取 完…

C++初学者指南第一步---9.函数

C初学者指南第一步—9.函数 文章目录 C初学者指南第一步---9.函数1.输入和输出1.1第一个例子1.2返回类型1.3函数参数常量参数默认值参数 1.4函数重载 2.函数执行2.1递归2.2 声明和定义 3.函数设计3.1约定3.2 特性[[nodiscard]] &#xff08;C17&#xff09;3.3 不抛出异常保证&…

C语言入门2-数据类型、运算符和表达式

变量命名 命名规范 只能由字母&#xff08;含"_"&#xff09;和数字组成&#xff1b;首字母不能是数字&#xff1b;不能与关键字重名&#xff0c;例如float、double和if等。 注意事项 不使用"_"开头&#xff0c;因为很多库函数这样命名&#xff0c;容易…

【Java】已解决java.sql.SQLRecoverableException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.sql.SQLRecoverableException异常 在Java的数据库编程中&#xff0c;java.sql.SQLRecoverableException是一个重要的异常&#xff0c;它通常表示一个可以恢复的SQL异常。…

思维导图之计算机网络整体框架

高清自行访问&#xff1a;计算机网络整体框架 (yuque.com)

汽车信息安全硬件讨论:SE vs HSM

目录 1.什么是Secure Element 2.芯片内置HSM和SE 3.未来HSM的发展 现在的智能网联汽车看起来像是一个连接万物的智能移动终端&#xff0c;它不仅可以与OEM云服务器通信接收OTA推送&#xff0c;还可以与手机蓝牙、Wifi交互完成远程汽车解锁、座舱内环境设置等等&#xff0c;借…

微信小程序 this.setData高级用法(只更改单个数据)

合理使用 setData | 微信开放文档 1、页面 <view class"h-100px"></view> <view>最简单的数据&#xff1a;</view> <button bind:tap"handleAdd" data-type"1">点我加 1&#xff1a; {{text}}</button> &…

计算几何【Pick定理】

Pick 定理 Pick 定理&#xff1a;给定顶点均为整点的简单多边形&#xff0c;皮克定理说明了其面积 A {\displaystyle A} A 和内部格点数目 i {\displaystyle i} i、边上格点数目 b {\displaystyle b} b 的关系&#xff1a; A i b 2 − 1 {\displaystyle Ai{\frac {b}{2}}…

【Python驯化-01】python中set去重数据每次结果不一致问题解决

【Python驯化-01】python中set去重数据每次结果不一致问题解决 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注…