结构体所占内存的字节数——内存对齐

本文介绍了内存对齐相关知识。首先阐述了内存对齐中对齐参数的确定,它由变量自身和编译器默认参数决定,不同编译器对double类型对齐方式有差异,还可通过#pragma pack改变默认对齐。接着说明了内存对齐是为提高程序性能,未对齐内存访问需多次操作,自然对齐能减少访问次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么是内存对齐?

下面先来看一个例子:

#include <stdio.h>
int main()
{
    struct Text1
    {
	char c1;
	short s;							
	char c2;
	int i;
    };
     struct Text2
    {
	char c1;
	char c2;
	short s;
	int i;
    };
    printf("%ld\n",sizeof(struct Text1));		//12    GCC下编译的结果
    printf("%ld\n",sizeof(struct Text2));		//8
	
    return 0;
}

解析:
在windows系统32位平台上:
int占4个字节
char占1个字节
float占4个字节
double占8个字节
1、首先确定对齐参数:对齐参数是由变量的自身对齐参数和编译器默认的对齐参数一起确定的!它是结构体中所有变量的自身对齐参数的最大值和系统默认参数中较小的那一个!(含有double类型的除外,原因如下!)而变量的自身对齐参数是由CPU字节长度(32位为4)和变量本身的字节长度中的较小的那一个(即变量的自身对齐参数<=4),所以本题中的对齐参数为4!
2、知道了对齐参数为4,即知道了分配单位就是4!
 

这里需注意的是:
VC和GCC默认的都是4字节对齐,编程中可以使用#pragma pack(n)指定对齐模数。出现以上差异的原因在于,VC和GCC中对于double类型的对齐方式不同。
Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则: 任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而char类型数据(1字节)则可以从任何一个地址开始。
Linux下的GCC奉行的是另外一套规则:任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数!

#prama pack()能改变编译器的默认对齐方式!例如

#pragma pack(n)                     //编译器将按照n字节对齐

#pragma pack()                       //编译器将取消自定义字节对齐方式

在#pragma pack(n)和#pragma pack()之间的代码按n字节对齐! 此为强制对齐!

2、为什么会有内存对齐?

字、双字和四字在自然边界上不需要在内存中对齐。对字、双字和四字来说,自然边界分别是偶数地址、可以被4整除的地址和可以被8整除的地址。无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;然而,对齐的内存访问仅需要进行一次访问。

一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问中未对齐的数据。

补充:
自然对齐指的是将对应变量类型存入对应地址值的内存空间,即数据要根据其数据类型存放到以其数据类型为倍数的地址处。例如char类型占1个字节空间,1的倍数是所有数,因此可以放置在任何允许地址处,而int类型占4个字节空间,以4为倍数的地址就有0,4,8等。编译器会优先按照自然对齐进行数据地址分配

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值