C语言结构体的大小,结构体内存对齐

news2024/10/7 10:21:10

1. 结构体的大小

在自己正真了解过之前,一直认为结构体的大小就是结构体内部成员大小的总和。

但当你去尝试打印结构体的大小时,会发现事实并非如此,也不会像你想的那样简单。

#include <stdio.h>

struct S1
{
    char c1;
    char c2;
    int i;
};

struct S2
{
    char c1;
    int i;
    char c2;
};

int main()
{
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    return 0;
}

给出这样的两个结构体,它们的元素完全相同,只是定义的顺序不一样。

按照直觉来说,它们的大小都应该是两个字符和一个整形的大小的总和,也就是6。

但是当我们实际打印出来之后会发现,struct S1的大小是8,而struct S2的大小是12。

也就是说,结构体的大小肯定不只是由其成员的大小和数量决定,至少还会与其成员定义的顺序有关。

那么,结构体的大小到底存在着什么样的机制呢?

这个所谓的机制,就是结构体内存对齐。

2. 结构体内存对齐

结构体内存对齐,就是指结构体成员在被定义时所分配到的空间并不是连续的,而是会基于不同变量对齐数的不同,去对应某些固定的位置的空间。

2.1 为什么要对齐

按理来说,对齐应该会导致元素因为没有紧密排列而造成空间的浪费,那么为什么要对齐呢?

2.1.1 平台原因

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

2.1.2 性能原因

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

以struct S2为例:

struct S2
{
    char c1;
    int i;
    char c2;
};

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

2.2 对齐规则

1. 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量(相距的字节数)为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。

- VS 中默认的值为 8

- Linux中 gcc 没有默认对齐数,对齐数就是成员自身的大小

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

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

2.3 举例

2.3.1 struct S1

struct S1
{
    char c1;
    char c2;
    int i;
};

1. c1作为第一个成员,在结构体的首地址处;

2. c2对齐数为1,所以紧贴着上一个元素;

3. i对齐数为4,由于前四格空间已经被占用,所以i向后寻找到的第一个为4的倍数的地址如图;

4. 最大对齐数为4,而8刚好是4的倍数,于是结构体大小为4。

2.3.2 struct S2

struct S2
{
    char c1;
    int i;
    char c2;
};

1. c1作为第一个成员,在结构体的首地址处;

2.  i对齐数为4,由于前四格空间已经被占用,所以i向后寻找到的第一个为4的倍数的地址如图;

3. c2对齐数为1,紧贴着前面一个元素;

4. 最大对齐数为4,目前结构体已经占用了9个字节,由于结构体的大小需要是4的倍数,所以其大小只能为12了。

2.3.3 其他

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

struct S4//32
{
    char c1;
    struct S3 s3;
    double d;
};

这两个案例可以自己尝试一下,要自己动手才能记得牢,不是我懒得写。

2.4 修改默认对齐数

用“#pragma()”这个预处理指令,可以修改默认对齐数。

#pragma pack(4)//默认对齐数改为4
#pragma pack()//恢复默认对齐数
#pragma pack(1)//等价于不对齐

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

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

相关文章

【C++精简版回顾】19.异常处理

1.throw抛出问题 int print(int a,int b) {if (b 0)throw b;return a / b; } 2.try与catch解决问题 try {print(2, 0); } catch (int b) {cout << "竟然是&#xff1a;"<<b<<endl; } 结果&#xff1a; 补充1&#xff1a;可以抛出字符串等 1.throw…

建站人的心酸:发了个官网加固通知,有公司关门的,还有吐槽的。

最近客户网站不是老被攻击么&#xff0c;所有节前发了个网站加固的通知&#xff0c;大部分客户都能理解和支持&#xff0c;也有客户倒闭的&#xff0c;也有想省钱结果费钱的&#xff0c;还有吐槽的。 尊敬的客户&#xff1a; 鉴于近期网络攻击频发&#xff0c;导致少部分客户…

Django学习记录08——图表及文件上传案例

1.图表Echarts的应用 Apache ECharts 1.1 使用方法 引用echarts.js即可到官方文档中查询使用 1.2 常用图标的使用 图表展示页面的部署&#xff08;主要展示折线图、柱状图、饼图&#xff09; {% block content %}<div class"container"><div class&qu…

To 有缘看到的朋友,To myself

To 有缘看到的朋友&#xff0c;To myself 零、00时光宝盒 我们生而为人&#xff0c;而不是什么神仙妖怪&#xff0c;自然逃不脱凡尘种种不易。 世界并不完美&#xff0c;面对很多事情我们都很无奈甚至悲哀&#xff0c;但生活总要继续下去&#xff0c;当困难悄悄地来临&#xff…

薪资18K需要什么水平?来看看97年测试工程师的面试全过程…

我的情况 大概介绍一下个人情况&#xff0c;男&#xff0c;本科&#xff0c;三年多测试工作经验&#xff0c;懂python&#xff0c;会写脚本&#xff0c;会selenium&#xff0c;会性能&#xff0c;然而到今天都没有收到一份offer&#xff01;从年后就开始准备简历&#xff0c;年…

【Apache Camel】基础知识

【Apache Camel】基础知识 Apache Camel是什么Apache Camel基本概念和术语CamelContextEndpointsRoutesRouteBuilderComponentsMessageExchangeProcessorsDomain Specific Language&#xff08;DSL&#xff09; Apache Camel 应用执行步骤Apache Camel 示意图参考 Apache Camel…

【ArcGIS超级工具】基于ArcPy的矢量数据批量自动化入库工具

最近&#xff0c;有很多做规划的朋友私信我&#xff0c;想让我帮忙开发一款ArcGIS自动化脚本工具&#xff0c;实现点、线、面的自动化入库操作&#xff0c;帮他们在平时的内业数据处理工作中减少机械式重复性的工作&#xff0c;提高工作效率。为此&#xff0c;我详细了解了下目…

第一套试卷

1.队列的链式操作 循环链表实现的链式队列中&#xff0c;头指针的变动主要取决于队列的操作。一般来说&#xff0c;在循环链表队列中&#xff0c;头指针front指向队列的头节点&#xff0c;尾指针rear指向队列的尾节点的下一个位置。 当进行入队&#xff08;插入&#xff09;操…

基于词袋模型的场景识别(附源代码!!!)

目录 1. 任务要求2. 数据集3. 实现算法4. 实验结果5. 源代码 1. 任务要求 输入&#xff1a;给定测试集图片&#xff0c;预测在15个场景中的类别。任务&#xff1a; 实现Tiny images representation。实现最近邻分类器nearest neighbor classifier。实现SIFT特征词袋表示 输出&…

diffusion model (扩散模型)原理

扩散模型分为正向过程和反向过程。 正向过程为一点点在图片上添加噪声的过程&#xff0c;反向过程为去噪声的过程。 图片的生成就是反向过程&#xff0c;给一张高斯噪声图片&#xff0c;逐步去噪生成图片。 扩散模型和VAE的区别&#xff0c; VAE是一步到位的&#xff08;通过…

中文版国产Figma简单好上手

在过去的两年里&#xff0c;国内外协同办公室发展迅速。一方面&#xff0c;它是由突如其来的疫情推动的&#xff0c;另一方面&#xff0c;它是科学技术不断进步的必然结果。在市场的推动下&#xff0c;市场上出现了越来越多的协同办公软件&#xff0c;使工作场所的工作更加高效…

Java开发避坑指南,手把手教你写Java项目文档

前言 作为一个有丰富经验的微服务系统架构师&#xff0c;经常有人问我&#xff0c;“应该选择RabbitMQ还是Kafka&#xff1f;” 基于某些原因&#xff0c; 许多开发者会把这两种技术当做等价的来看待。的确&#xff0c;在一些案例场景下选择RabbitMQ还是Kafka没什么差别&…

2.Rust变量

变量的声明 let关键字 在Rust中变量必须要先声明才能使用&#xff0c;let关键字用于声明变量并将一个值绑定到该变量上。如下: fn main() {let var_name:i32 123123;println!("{}",var_name) //println! 是一个宏&#xff08;macros&#xff09;&#xff0c;可以…

遇见未来的你——陪伴是最长情的告白

目录 一、背景介绍二、思路&方案三、过程1.家庭中彼此的陪伴最长情2.事业中与合伙人与同事与朋友与产品的陪伴最长情3.人生中与计划与落实与啊哈的陪伴最长情4.肉体与灵魂分分合合的体验 四、总结 一、背景介绍 人有时候一转身就是一辈子&#xff0c;所以珍惜转身的每一个…

如何计算搭建光伏电站需要多少成本?

光伏电站&#xff0c;又称太阳能电站&#xff0c;是一种利用太阳能发电的电力系统。随着全球对可再生能源的需求日益增加&#xff0c;光伏电站的建设变得越来越普遍。然而&#xff0c;在投资光伏电站之前&#xff0c;了解其建设成本是非常重要的。本文将介绍如何计算搭建光伏电…

96、C++ 性能优化一览

在对 C++ 版本的 resnet50 经过大约 5 个版本的优化之后,性能也基本达到了预期。至少利用手写的 resnet50 在 CPU 上推理一张图片感觉不到卡顿了。 下面对这几个版本的性能优化做一个总结。 初始版本1 第一版本的 C++ 代码,并没有考虑性能问题,仅仅是想按照手写 resnet50 …

【学习】torch.nn.CrossEntropyLoss交叉熵损失函数

交叉熵损失函数torch.nn.CrossEntropyLoss 交叉熵主要是用来判定实际的输出与期望的输出的接近程度&#xff0c;为什么这么说呢&#xff0c;举个例子&#xff1a; 在做分类的训练的时候&#xff0c;如果一个样本属于第K类&#xff0c;那么这个类别所对应的输出节点的输出值应…

腾讯云服务器99元一年是真的吗?只要61元!

腾讯云服务器99元一年是真的吗&#xff1f;假的&#xff0c;不要99&#xff0c;只要61元&#xff01;又降价了&#xff01;腾讯云服务器多少钱一年&#xff1f;61元一年起&#xff0c;2核2G3M配置&#xff0c;腾讯云2核4G5M轻量应用服务器165元一年、756元3年&#xff0c;4核16…

腾讯云服务器99元一年是真的吗?又降价,现在只要61元

腾讯云服务器99元一年是真的吗&#xff1f;又降价&#xff0c;现在只要61元。腾讯云服务器多少钱一年&#xff1f;61元一年起&#xff0c;2核2G3M配置&#xff0c;腾讯云2核4G5M轻量应用服务器165元一年、756元3年&#xff0c;4核16G12M服务器32元1个月、312元一年&#xff0c;…

【好书推荐-第九期】Sora核心技术相关书籍《扩散模型:从原理到实战》与《GPT 图解:大模型是怎样构建的》:Sora的两大核心技术,都藏在这两本书里!

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公众号&#xff1a;洲与AI。 &#x1f388; 本文专栏&#xff1a;本文收录…