【C语言】结构体字节对齐以及内存分配原理(一)

1.Win32平台下的微软C编译器采用的对齐规则:
任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而char类型数据(1字节)则可以从任何一个地址开始。
2. Linux下的GCC的规则:
任何2字节大小的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如Long和double)都以4为对齐模数。
3.其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:
  1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;   
  2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
  3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
4.#pragma pack限定的对齐模数:
#pragma pack指定的数值与结构体内最大的基本数据类型成员长度相比较得到的数值较小者
5.一般情况下的数据自身对齐:

数据类型变量存放的起始地址相对于结构体的起始地址的偏移量
char1
short2
int4
long4
float4
double8

6.以win32为例的数据对齐及内存分配
1)在没有#pragma pack宏的情况下:
举例:

#include<stdio.h>
struct A
{
	int a;
	char b;
	short c;
}str;

int main()
{
	printf("struct size = %ld \n", sizeof(struct A));
	printf("par a address (16)=%p, (10)= %ld \n", &str.a, &str.a);
	printf("par b address (16)=%p, (10)= %ld \n", &str.b, &str.b);
	printf("par c address (16)=%p, (10)= %ld \n", &str.c, &str.c);
	return 0;
}

内存分配状态:
在这里插入图片描述
说明:32位地址0x…44能被结构体中最大的字节数4整除,int a占4字节,char b对齐模数为1,short c原本是从0x…49开始存,但是,c的对齐模数为2,结构体起始地址0x…44到0x…49占5字节,不是2的整数倍,不符合,往下找,0x…4a满足要求,且所有的字节加起来为8,是最大字节数的4的2倍,满足要求,所以长度为8

变换一下位置:

#include<stdio.h>
struct A
{
	char b;
	int a;
	short c;
}str;

int main()
{
	printf("struct size = %ld \n", sizeof(struct A));
	printf("par b address (16)=%p, (10)= %ld \n", &str.b, &str.b);
	printf("par a address (16)=%p, (10)= %ld \n", &str.a, &str.a);
	printf("par c address (16)=%p, (10)= %ld \n", &str.c, &str.c);
	return 0;
}

内存分配状态:
在这里插入图片描述
说明:char b对齐模数为1,int a 存放的位置到结构体起始的位置需是4的倍数,所以0x…41,0x…42,0x…43不符合,0x…44符合,把a放到这里,占4字节,short c从0x…48开始存,占2字节,所有的字节加起来为10,不是最大字节数的4的倍数,不满足要求,填充2个字节使其成为4的倍数,所以长度为12
2)有#pragma pack宏的情况下:
举例:

#include<stdio.h>
#pragma pack(2)
struct A
{
	char b;
	int a;
	short c;
}str;

int main()
{
	printf("struct size = %ld \n", sizeof(struct A));
	printf("par b address (16)=%p, (10)= %ld \n", &str.b, &str.b);
	printf("par a address (16)=%p, (10)= %ld \n", &str.a, &str.a);
	printf("par c address (16)=%p, (10)= %ld \n", &str.c, &str.c);
	return 0;
}

内存分配状态:
在这里插入图片描述
说明:pragma pack(2) 与4对比,2小,则str的对齐模数为2,char b存放占1字节,int a 存放的位置到结构体起始的位置需是2的倍数,所以0x…41不符合,0x…42符合,把a放到这里,占4字节,short c从0x…46开始存,占2字节,所有的字节加起来为8,是2的倍数,满足要求,所以长度为8。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值