c语言之内存对齐

从结构体的长度问题说起

在学习结构体的时候,老师留下了一个很有意思的问题:

#include<stio.h>
#include<string>
struct Node
{
    
    
	char name;
	int string;
	char ssex;
	
};
int main()
{
    
    
	int size;
	size = sizeof(Node);
	printf("%d   ", size);
	system("pause");
	return 0;
}

很明显,我们是在求一个结构体所占的字节个数;如果没有接触到内存对齐的概念,大概率会脱口而出一个答案:6。因为char占一个字节,int占4个字节,1+4+1=6,所以结构体的所占字节大小是6。当然,这是错误的,当我们打开编译器编译运行的时候,发现结果给的是:12。而我们仅仅调换一下结构体中的顺序,

#include<stio.h>
#include<string>
struct Node
{
    
    
	char name;
	char ssex;
	int string;

};
int main()
{
    
    
	int size;
	size = sizeof(Node);
	printf("%d   ", size);
	system("pause");
	return 0;

此时编译器编译运行的时候,我们会发现,运行的结果又是:8;到底结果是如何出来的,值得探讨。

内存对齐规则

1)结构体变量的首地址是其最长基本类型成员的整数倍

2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍

3)结构体的总大小为结构体最宽基本类型成员大小的整数倍

具体规则摘自百度百科,直接根据以上规则来进行讲解吧。
对于以上第一个程序,由于结构体的第一个数据类型是char,毫无疑问,根据规则1,占1个字节,所以在此时结构体的字节数是1。而到了int型时,由于int占4个字节,根据规则2,则必须是由偏移量,使其长度是4的倍数开始,所以,增加了3个偏移量,从4开始,加上int所占的4个字节,结构体的长度来到了8。而到了最后一个char,所占字节个数是1,但是根据规则3,总得大小必须是最宽类型整数倍,所以从8开始的时候,毫无疑问需要加上1,以及3个偏移位,使其总长度来到12来保证3个规则全部满足。所以最终的结果来到了12。

而对于第二个程序,由于结构体的第一个数据类型是char,毫无疑问,根据规则1,占1个字节,所以在此时结构体的字节数是1,而第二个也是char,只需要继续加1即可,总长度来到了2,到了第三个int类型,因为int占4个字节,根据规则2,则必须是由偏移量,使其长度是4的倍数开始,所以,增加了2个偏移量,首地址来到了4,从4开始,加上int所占的4个字节,结构体的长度来到了8。
再来看个例子:

#include<stdio.h>
#include<string>
struct Date
{
    
    
	char dada;
	int name;
	int score;  
};
struct node
{
    
    
	char name;
	char sddd;
	char ssex;
	int daef; 
	Date vie; 
	double dae;  
};
int main()
{
    
    
	int size;
	size = sizeof(node);
	printf("%d   ", size);
	system("pause");
	return 0;
}

我们依然使用上述规则,从main函数自上从下开始,首先是3个char型,字节个数来到了3。而接下来的int根据以上规则,偏移一个偏移量,从4开始,加上本身的4个字节,总长度来到8。然后又遇到了一个结构体变量,目光转到前面结构体Date中,首先是char,长度来到了1,又是int,首先偏移3来到4,再加上4个字节,长度来到了8,最后再加上一个int来到了12,所以Date的总长度是12,最宽是4.所以,node中的字节数从8开始,加上12,总长度是20,。由于最后一个是double,长度为8,所以需要总长度偏移4,来到24,再加上8.所以node的总字节数是:32.

猜你喜欢

转载自blog.csdn.net/ALITAAAA/article/details/103043116