C语言如何计算结构体大小(结构体的内存对齐)

这篇具有很好参考价值的文章主要介绍了C语言如何计算结构体大小(结构体的内存对齐)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:

结构体的内存对齐是有关结构体内容的很重要一个知识点,主要考察方式是计算结构体的字节大小。

引言:

当我们对计算结构体一无所知,我们不妨自己思索如何计算,是不是直接计算结构体成员变量占用内存的大小呢?

那我们先举个例子

struct s1
{
	int i;
	char a;
	char b;
};

struct s2
{
	char a;
	int i;
	char b;
};

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

C语言如何计算结构体大小(结构体的内存对齐),C语言,算法,数据结构

 观察发现结构体的大小计算跟我们想的很不一样。

不应该是两个char类型,一个int类型,2*1+4答案不应该是6吗?

上面两个结构体内容是一样的,只有顺序不一样,为何计算结果不一样呢?

我们就带着以上的疑问去探索!

一、计算偏移量

我们要研究明白结构体的成员列表在内存中到底是如何存储的,首先要知道结构体的各个成员变量在内存中相较于起始位置的偏移量。这时候要引用到offsetof,这个可以计算结构体成员相较于结构体起始位置的偏移量

使用宏offsetof

 如何使用宏offsetof?

C语言如何计算结构体大小(结构体的内存对齐),C语言,算法,数据结构

首先有头文件:#include<stddef.h>

参数是类型,和成员名,返回值就是结构体成员相较于结构体起始位置的偏移量。

我们先试着打印下s2各个成员关于结构体起始位置的偏移量。

发现结果是0、4、8,我们可以画一张内存图进行理解。

C语言如何计算结构体大小(结构体的内存对齐),C语言,算法,数据结构

如图所示,根据offsetof我们可以得到这样的内存存储模式,但是这样一共也就9个字节,后面的3个字节从何而来?中间多出来的3个字节又从何而来?

我们继续探索。

结构体到底如何计算?

二、结构体的对齐规则

我们经过上面的分析,发现结构体成员不是按照顺序在内存中连续存放的,而是有一定的对齐规则,接下来我们就研究结构体的内存规则。

  1. 结构体的第一个成员永远放在相较于结构体变量的起始未知的偏移量为0的位置
  2. 从第二个成员开始,往后的每个成员都要对齐到某个对齐数的整数倍处。(对齐数:结构体成员自身大小和默认对齐数的较小值)VS上默认对齐数是8,gcc没有默认对齐数,对齐数就是变量本身的大小。
  3. 结构体的总大小,必须是最大对齐数的整数倍,最大对齐数是:所有成员的对齐数中最大的值
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

三、总结计算方法

我们首先要知道结构体变量成员的自身字节大小,然后去寻找对齐数,对齐数的寻找方法就是将自身字节大小和默认对齐数比较,取较小值,这样先找到对齐数,然后根据自身的字节大小去填充,就完成了成员在内存中的存储,最后在所有的成员已经结束存储,再计算最大对齐数(所有成员的对齐数中最大值),这样就完成了计算!

我们既然已经知道规则和计算方法,就让我们小试牛刀一下~

四、练习

练习一:

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

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

C语言如何计算结构体大小(结构体的内存对齐),C语言,算法,数据结构

上面图片的写法就是左边是本身成员变量的字节大小,右边是默认对齐数进行比较,最后再从对齐数中找出最大值,就是最大对齐数,所以最后0~15就是存储结构体的大小,也就是一共16个字节

 练习二:

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

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

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

上面是嵌套结构体场景,结构体S3本身大小是16,需要对齐到自身最大对齐数的位置,也就是8,然后double类型的对齐数是8,最后总字节大小也满足最大对齐数,所以一共32个字节。

C语言如何计算结构体大小(结构体的内存对齐),C语言,算法,数据结构

五、为什么存在内存对齐?

1、平台原因

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

2、性能原因

数据结构(尤其是栈)应该尽可能在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

总体来说

结构体的内存对齐,就是让空间换时间。 

TIP:

我们在设计结构体时,可以人为的节省空间——让占用空间小的成员尽量集中在一起

C语言如何计算结构体大小(结构体的内存对齐),C语言,算法,数据结构

 例如我们之前举的例子,尽管两个结构体存的成员变量一样,但是顺序不一样,结构体内存大小也是不同。

六、修改默认对齐数

对,你没有听错,默认对齐数是可以修改滴,当我们把默认对齐数修改为1时,结构体的成员变量就是连续存储的。代码如下,计算出来的大小就是4+1+8=13文章来源地址https://www.toymoban.com/news/detail-591069.html

#pragma pack(1)//修改默认对齐数为1
struct s
{
	int a;
	char b;
	double c;
};
#pragma pack()//修改默认对齐数为默认

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

到了这里,关于C语言如何计算结构体大小(结构体的内存对齐)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言高阶篇】C语言面试必考知识点,结构体的内存对齐我看还有谁不会!

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 :《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位宝子们大家好啊,今天给大家带来的是结构体的内存对齐这部分知识,可以说是干货满满啦!    ⛳️ 在我们C语言的面试题中,结构体最

    2024年02月16日
    浏览(48)
  • 【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参

    本小节,我们学习结构的内存对齐,理解其对齐规则,内存对齐包含结构体的计算,使用宏 offsetof 计算偏移量,为什么要存在内存对齐?最后了解结构体的传参文章干货满满!学习起来吧😃! 结构体内存对齐指的是 结构体中各成员变量在内存中的存储位置按照一定规则对齐

    2024年02月04日
    浏览(46)
  • C语言之结构体内存对齐与内存的简单理解

    文章目录 内存单元的理解 结构体中内存对齐的规则 为什么会存在内存对齐 首先先要介绍一下C语言中一些常见的存储单元     bit       存放一个二进制位     Byte   1Byte = 8 bit     KB     1KB   = 1024 Byte     MB     1MB   = 1024 KB     GB     1GB   = 1024 MB     TB 

    2023年04月26日
    浏览(44)
  • C语言——结构体类型(二)【结构体内存对齐,结构体数组】

    📝前言: 上一讲结构体类型(一)中,我们讲述了有关 结构体定义,创建,初始化和引用 的内容,这一讲,我们进一步学习结构体的相关知识: 1,结构体内存对齐 2,结构体数组 🎬个人简介:努力学习ing 📋个人专栏:C语言入门基础 🎀CSDN主页 愚润求学 🌄每日鸡汤:

    2024年01月24日
    浏览(70)
  • 【C语言高阶篇】结构体 —— 什么是内存对齐?

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 :《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位宝子们大家好啊,今天给大家带来的是结构体的内存对齐这部分知识,可以说是干货满满啦!    ⛳️ 在我们C语言的面试题中,结构体最

    2024年02月14日
    浏览(51)
  • 深入了解C语言中的结构体类型与内存对齐

    在C语言中,结构体是一种 自定义的数据类型 , 它允许我们将不同类型的数据组合在一起,形成一个新的数据类型 。结构体的使用为我们解决了一些复杂数据的表示和处理问题,不仅限于单单的整型或者字符。本文将深入探讨结构体类型、结构体变量的创建和初始化,并详

    2024年04月11日
    浏览(43)
  • C语言结构体字节对齐(内存对齐)之#pragma pack和__attribute__((packed)的使用

    在不使用 #pragma pack 和 __attribute__((packed) 等选项来自定义字节对齐大小的情况下,关于正常字节对齐的描述,可参考博文: C/C++计算类/结构体和联合体(union)所占内存大小(内存对齐问题)_联合体占用的内存空间_SOC罗三炮的博客-CSDN博客 同学可以尝试将char f 注释,最后将

    2024年02月12日
    浏览(46)
  • 结构体(结构体内存对齐)+位段+枚举

    本期带大家一起来学习一下 结构体知识+位段知识+枚举知识 🌈🌈🌈 1.1 结构体的声明✈️✈️ 1.1.1 结构体的完全声明🚀 结构体是一种自定义的类型,🔦🔦 结构体是将不同类型的数据按照一定的功能需求进行整体封装 ,封装的数据类型与大小均可以由用户指定。 那么又

    2023年04月10日
    浏览(40)
  • 结构体内存对齐(面试重点)

    1.1 结构体的概念 结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.1.1 结构的声明 例如描述⼀个学⽣: 1.1.2 结构体变量的创建和初始化 运行结果如图: 1.2 结构的特殊声明 在声明结构的时候,可以不完全的声明。 比如: 上⾯的两个结构

    2024年01月25日
    浏览(43)
  • 结构体内存对齐,位段,枚举相关问题.

    本文标签:    结构体内存对齐   结构位段问题   枚举 文章目录 目录 文章目录 一、结构体的内存对齐. 1.计算结构体大小 2.为什么存在内存对齐? 二、结构体的位段问题. 三、枚举 1.枚举类型定义 2.枚举的优点 为什么使用枚举? 总结 知道了结构体的基本使用,我们可以深入探

    2023年04月08日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包