首页 > 系统相关 >结构体中的内存对齐

结构体中的内存对齐

时间:2024-04-11 13:04:10浏览次数:23  
标签:struct int char 内存 体中 对齐 结构

结构体中的内存对齐

内存对齐规则
在C语言中,结构体的内存布局并不是简单地将成员依次排列在内存中,而是遵循一定的内存对齐规则。这些规则确保了数据结构在内存中存储的方式既高效又符合硬件平台的限制。

问题提出

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

运行结果:在这里插入图片描述
许多小伙伴也许会疑惑为什么两个结构体的大小不一样呢?
这里我们就要提出今天的主题:结构体中的内存对齐
由上述的代码结构我们可以得出结果分析得出:结构体成员不是按照顺序在内存中连续存放的,而是有一定的对齐规则;

具体规则

首个成员对齐:结构体的第一个成员从偏移量为0的位置开始存储。
后续成员对齐:从第二个成员开始,每个成员都要对齐到其大小和平台默认对齐数之间的较小值。
结构体总大小:结构体的总大小必须是所有成员对齐数中的最大值的所有倍数。
嵌套结构体对齐:嵌套结构体对齐到的是内部最大对齐数的倍数。
这些规则确保了结构体在内存中的布局优化,提高访问效率,并符合不同硬件平台的限制。
下面我们以具体的实例来深入理解上述规则(默认对齐数是8):
eg1:

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

我们可以通过画内存示意图来解释为什么S1的内存大小为12
在这里插入图片描述

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

在这里插入图片描述
通过上述两个例子我们可以得出,即使两个结构体中的成员变量一样,但顺序不一样也会影响结构体的大小。
在设计结构体,既要对齐,又要节省空间的做法是:
让占用空间小的成员尽量集中在一起。

对齐原因

为什么会出现内存对齐这样的规则呢?一般来说有两个方面的原因:
1.平台原因:
不是所有的硬件平台都支持访问任意地址的任意数据,某些硬件平台只能支持在某些特定类型的数据,否则会抛出硬件异常。
2.性能原因:
数据结构(栈)应尽可能地在自然边界上,原因在于为了访问未对齐的内存,处理器上需要两次访问,如果对齐只需要一次访问。
总的来说:
结构体的内存对齐是一种拿空间换时间的做法。

修改默认对齐数

#pragma pack(N)//将默认对齐数修改为N

结构体

##pragma pack()//取消默认对齐数

结构体传参

#include<stdio.h>

struct S
{
	int data[100];
	int num;
};

void Print1(struct S s)
{
	printf("%d\n", s.num);
}

void Print2(struct S* s)
{
	printf("%d\n", s->num);
}

int main()
{
	struct S s = { {1,2,3},100 };
	Print1(s);
	Print2(&s);
	return 0;
}

在这里插入图片描述
上述Print1和Print2两种传参方式都是可行的,但优选Print2
原因:
函数传参时,参数需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象,结构图过大,参数压栈的系统开销会比较大,导致性能下降
结论:
结构体传参数,要传结构体的地址

总结

结构体内存对齐是C语言中一项重要的内存管理特性,它优化了数据的存储和访问效率。在设计数据结构时,应考虑对齐规则,以达到性能和空间的最佳平衡。

标签:struct,int,char,内存,体中,对齐,结构
From: https://blog.csdn.net/qq_67411584/article/details/137593188

相关文章

  • Adobe Reader XI 11.0.23 简体中文版
    下载地址:AdobeReaderXI11.0.00简体中文版http://ardownload.adobe.com/pub/adobe/reader/win/11.x/11.0.00/zh_CN/AdbeRdr11000_zh_CN.exeAdobeReaderXI11.0.23补丁http://ardownload.adobe.com/pub/adobe/reader/win/11.x/11.0.23/misc/AdbeRdrUpd11023.msp注意:先请安......
  • P8791 [蓝桥杯 2022 国 AC] 内存空间 题解
    题面一道比较简单模拟题,但是要分类讨论一.读完题你应该知道的1.输入一共有T+1行,输入含有空格。(处理1)2.对于每一行变量定义的语句,只会出现一种变量类型,type只可能是int或long,只有一个分号。(处理1,处理2)3.统计内存过程中用B做单位,保证一定有输出,但在输出时要换......
  • 内存管理new and delete(C++)
        在本篇中,将会较为详细的介绍在Cpp中的两个新操作符new和delete,将会介绍其中的底层原理,以及这两个操作符的使用方法。其中还介绍了new/delete操作符使用的细节,还扩展了一些有关定位new表达式的知识点。最后总结了malloc/free与new/delete的区别。目......
  • cpp 内存分区模型
    c++程序在执行前,将内存大方向划分为4个区域。1.代码区:存放函数的二进制代码,有操作系统进行管理2.全局区:存放全局变量和静态变量以及常量3.栈区:由编译器自动分配释放,存放的函数参数和局部变量4.堆区:由程序员分配释放,若程序员不分配释放,程序结束时由操作系统回收不同区域存......
  • Win11开机内存占用高的解决办法。
    我自己本身的配置是双16G的,升级完win11以后,开机没有打开任何软件,发现内存占用达到25%,7.9个G。 解决办法: 使用windows内存诊断工具可以降一部分。 快捷键win+r 输入 mdsched 选择第一个,立即重新启动。接下来的画面: 可以让开机内存减小。亲测暂时生效,后续再看......
  • Java IO与NIO-Java内存管理-Java虚拟机(JVM)-Java网络编程-Java注解(Annotation)
    JavaIO与NIO:请解释Java中的IO(Input/Output)和NIO(NewInput/Output)的区别是什么?它们各自的优势是什么?答案:Java中的IO是基于流(Stream)的方式进行输入输出操作,而NIO则是基于通道(Channel)和缓冲区(Buffer)的方式进行输入输出操作。NIO相比于IO具有非阻塞IO、选择器(Selector)和内存映......
  • 54、C++内存模型
    在 C++ 中,程序运行时,内存主要分成四个区,分别是栈、堆、数据段和代码段。                栈:存储局部变量、函数参数和返回值。堆:存储动态开辟内存的变量。数据段:存储全局变量和静态变量。代码段:存储可执行程序的代码和常量(例如字符常量),此存储区不可修......
  • 电脑硬件 - 内存
    内存,是一台电脑的CPU与硬盘间数据交互的中转站。不稳定的内存时常会导致蓝屏,黑屏,死机,甚至电脑无法亮机。在电脑工作中,CPU和硬盘间无时无刻地进行着大量的数据交互。为了保证软件流畅正常运行,会在中间加一个内存。 在工作时,金手指会与内存插槽内部的触点接触,若金手指接触不......
  • 将一个结构体里面的数据转为 小端对齐的二进制流
    现在有一个C++的结构体,需要把它转为二进制流,而且是小端对齐的。我们还需要将一个小端对齐的二进制流,转为对应的结构体。appendLittleEndianparseLittleEndian这2个方法是chatgpt提供给我的,功能能准确实现。代码也比较简洁。 #include<iostream>#include<vector>#inc......
  • Agent内存马分析
    什么是JavaAgent我们知道Java是一种强类型语言,在运行之前必须将其编译成.class字节码,然后再交给JVM处理运行。JavaAgent就是一种能在不影响正常编译的前提下,修改Java字节码,进而动态地修改已加载或未加载的类、属性和方法的技术。实际上,平时较为常见的技术如热部署、一些诊断工......