C语言学习小结_09_结构体的内存对齐

一、为什么存在内存对齐
下面有代码

#include<stdio.h>
#include<windows.h>
struct s1
{
    
    
	char c;
	int i;
	char c1;
};
struct s2
{
    
    
	char c;
	char c1;
	int i;
};
int main()
{
    
    
	printf("%d\n", sizeof(struct s1));
	printf("%d\n", sizeof(struct s2));

	system("pause");
	return 0;
}

在这里插入图片描述
两个结构体内部的成员变量的元素类型相同,但是两个结构体的大小不同,很是奇怪是不是。
其实CPU在访问结构体的内存地址的时候是有一定的规则的,要遵守这种规则---->结构体的内存对齐
那么为什么会存在内存对齐呢?
大部分的书籍和参考资料都是这样说的:
1、平台原因9(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:
数据结构(尤其是栈)应该尽可能在自然边界上对齐。原因在于为了访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存仅仅需要一次访问。
总的来说:结构体的内存对齐是拿空间来换时间的做法。(因为结构体内部为了访存的内存对齐的原则两个成员变量极有可能出现内存的镂空,就像上面的两个结构体相同的成员变量的不同排布方式却导致结构体的大小不同)
二、结构体内存对齐规则:
1 、第一个成员在与结构体变量偏移量为0的地址处
2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。也就是说起始偏移量能整除对齐数。
对齐数等于编译器一个默认的对齐数字(可以自己设置)与该成员变量大小的较小值,==>min(默认对齐数,成员大小)。
3、结构体的总大小为最大对齐数字(每个成员变量都有一个对齐数)的整数倍。
其中自定义类型,比如数组的最大对齐数为
=>min(其中一个元素的大小,编译器的默认对齐数),结构体本身的最大对齐数字为其成员变量对齐数字中最大的那一个。
来上代码,计算下吧。

#include<stdio.h>
#include<windows.h>
#pragma warning(disable:4996)

//结构体的内存对齐
typedef struct s1
{
    
    
	char c1;
	int i;
	char c2;
} s1_;
typedef struct s2
{
    
    
	char c1;
	char c2;
	int i;
} s2_;
typedef struct s3
{
    
    
	double c1;
	char c2;
	int i;
} s3_;
//结构体嵌套
struct s4
{
    
    
	char c1;
	struct s3 _s3;
	double d;
};
union Un2
{
    
    
	short c[7];
	int i;
};
//可以利用联合判断当前计算机的大小端存储
union Un1
{
    
    
	char c;
	int i;
};

int main()
{
    
    
	union Un1 un;
	un.i = 1;
	int ret = un.c;
	if (1 == ret){
    
    
		printf("小端机器!\n");
	}
	else{
    
    
		printf("大端机器!\n");
	}
	printf("%d字节\n", sizeof(union Un2));
	printf("%d字节\n", sizeof(s1_));
	printf("%d字节\n", sizeof(s2_));
	printf("%d字节\n", sizeof(s3_));
	printf("%d字节\n", sizeof(struct s4));

	
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CZHLNN/article/details/110006248