从结构体的长度问题说起
在学习结构体的时候,老师留下了一个很有意思的问题:
#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.