结构体内存对齐的原因:
在运行一个结构体时,编译器需要给结构体中的每个变量成员分配内存空间,如这样一个结构体中
typedef struct A
{
char c1;
int i;
int j;
}A;
对其内存空间分配问题进行分析,如若不进行内存对齐,它的内存空间是:
char类型变量c1占1个字节,紧接着int类型变量i与j分别占4个字节,总有9个字节,在访问时,如图1,访问次数较多;在图2中,总有12个字节空间,虽然浪费了c1后的三个字节空间,访问次数却变少,会很大程度上节省了时间,提高了效率。用一句话概括“浪费空间用来节省时间”,这就是结构对齐的主要原因。
结构体内存对齐求其大小:
首先来看这样一个结构体
typedef struct A
{
char c1;
int i;
}A;
int main()
{
A sa;
printf("%d\n",sizeof(A));
printf("%p\n",&(sa.c1));
printf("%p\n",&sa);
return 0;
}
其输出结果:8和两个相同地址。
在输出c1地址和sa的地址相同,所以结构体第一个成员变量是从内存的第一个字节空间开始的,接下来要思考为什么A的空间输出大小为8了?
首先,我们先要知道结构体默认对齐数在VS中为8,在Linux为4,现在以VS举例说明:
如上图中,char类型c1占用第一个字节,为偏移量为0的第一个字节(原因在上面已经解释),int类型变量i从偏移地址为4的字节空间开始占用四个字节,为什么从偏移地址为4这一字节开始,是以类型int字节数4的整数倍的偏移量的字节空间开始占用的,而上4的字节空间没被占用,所以从4开始,(同理char类型占用空间则为1的整数倍的偏移地址开始,double从8的整数倍的偏移地址开始等等),而结构体所占的位数要是结构体成员中所占位数最长的那个数据变量的整数倍,所以在此问题中4为最长,它的整数倍为8,所以占8个字节,c1后面的三个字节与浪费,但是与i对齐。
在举一个例子:
typedef struct s1
{
int i;
char j;
int a;
double b;
}s1
看到这个程序,首先明白这个结构体所占位数为double型字节为8的整数倍,然后分析:
int i占4个字节,char j占一个字节,j后面的3个字节浪费与i对齐;然后int a占四个字节,偏移地址从8开始到11,最后double b则从偏移地址16开始到23,所以总共占用24个字节空间,int a后的偏移地址12、13、14、15字节空间为了结构体对齐浪费掉,而24个字节正好为8的整数倍,所以当输出时其输出结果为:24
这就为结构体对齐的原因及求大小的基本知识,当然,在求大小时还有许多特殊情况,如:
(1)结构体中定义数组时的解法过程;
(2)结构体中嵌套另一个结构体时的解法过程等等
这些请看下一条博客的分析,这也是第一次第一条博客,所以以上分析可能有许多瑕疵与问题,还请能够指正指正!