C语言结构体大家都不陌生,本文讲解结构体在内存空间中的分配情况。
直接上验证代码(VS2010):
#include <stdio.h>
typedef struct
{
char a;
short b;
int c;
}test_t1;
typedef struct
{
int a;
short b;
char c;
}test_t2;
typedef struct
{
short a;
char b;
int c;
}test_t3;
typedef struct
{
short a;
int b;
char c;
}test_t4;
void main()
{
test_t1 test1;
test_t2 test2;
test_t3 test3;
test_t4 test4;
printf("sizeof(char) :%d\r\n",sizeof(char));
printf("sizeof(short):%d\r\n",sizeof(short));
printf("sizeof(int) :%d\r\n\r\n",sizeof(int));
printf("sizeof(test1):%d\r\n",sizeof(test1));
printf("sizeof(a):%d\r\n",sizeof(test1.a));
printf("sizeof(b):%d\r\n",sizeof(test1.b));
printf("sizeof(c):%d\r\n",sizeof(test1.c));
printf("&(test1):%4x\r\n",&(test1));
printf("&(a):%4x\r\n",&(test1.a));
printf("&(b):%4x\r\n",&(test1.b));
printf("&(c):%4x\r\n\r\n",&(test1.c));
printf("sizeof(test2):%d\r\n",sizeof(test2));
printf("sizeof(a):%d\r\n",sizeof(test2.a));
printf("sizeof(b):%d\r\n",sizeof(test2.b));
printf("sizeof(c):%d\r\n",sizeof(test2.c));
printf("&(test2):%4x\r\n",&(test2));
printf("&(a):%4x\r\n",&(test2.a));
printf("&(b):%4x\r\n",&(test2.b));
printf("&(c):%4x\r\n\r\n",&(test2.c));
printf("sizeof(test3):%d\r\n",sizeof(test3));
printf("sizeof(a):%d\r\n",sizeof(test3.a));
printf("sizeof(b):%d\r\n",sizeof(test3.b));
printf("sizeof(c):%d\r\n",sizeof(test3.c));
printf("&(test3):%4x\r\n",&(test3));
printf("&(a):%4x\r\n",&(test3.a));
printf("&(b):%4x\r\n",&(test3.b));
printf("&(c):%4x\r\n\r\n",&(test3.c));
printf("sizeof(test4):%d\r\n",sizeof(test4));
printf("sizeof(a):%d\r\n",sizeof(test4.a));
printf("sizeof(b):%d\r\n",sizeof(test4.b));
printf("sizeof(c):%d\r\n",sizeof(test4.c));
printf("&(test4):%4x\r\n",&(test4));
printf("&(a):%4x\r\n",&(test4.a));
printf("&(b):%4x\r\n",&(test4.b));
printf("&(c):%4x\r\n\r\n",&(test4.c));
}
输出结果:
结论:
- 默认情况下,结构体的大小是结构体中最长类型的整数倍。
- 结构体中的空间分布是按照结构体中最长类型对齐的。
- 结构体中不同类型的成员,一定是按照自己的类型对齐。比如,int型的起始地址一定是4的整数倍,short型的首地址一定是2的整数倍。。。
用上面的例子说明结论。
情况1:
typedef struct
{
char a;
short b;
int c;
}test_t1;
在内存中空间分布(根据上面示例实际分配空间):(a的大小本身是1字节,但是内存为他分配了2字节空间)
情况2:
typedef struct
{
int a;
short b;
char c;
}test_t2;
在内存中空间分布(根据上面示例实际分配空间):(c的大小本身是1字节,但是内存为他分配了2字节空间)
情况3:
typedef struct
{
short a;
char b;
int c;
}test_t3;
在内存中空间分布(根据上面示例实际分配空间):(b的大小本身是1字节,但是内存为他分配了2字节空间)
情况4:
typedef struct
{
short a;
int b;
char c;
}test_t4;
在内存中空间分布(根据上面示例实际分配空间):(a的大小本身是2字节,但是内存为他分配了4字节空间;c的大小本身是1字节,但是内存为他分配了4字节空间)
看明白了吗?结构体分配空间时,是顺序分配的,当分配到某一成员时,如果分配的地址没有按照该成员的类型对齐,那么往后找,直到找到按该成员类型对齐的地址。
再举例说明:
情况5:
typedef struct
{
int a;
long long b;
char c;
char d[6];
}test_t6;
上面的结构体分配空间如下:
longlong型在VS2010中占8字节,所以该结构体一共占24字节。实际输出验证下:
可以看到实际结果与理论一致。
再举一例:
情况6:
typedef struct
{
char a;
char b;
int c;
char d;
char e;
short f;
}test_t7;
上面的结构体分配空间如下:
该结构体一共占12字节。实际输出验证下:
可以看到实际结果与理论一致。
这种结构体对齐是默认情况下的对齐。实际使用中可以指定对齐方式,也可以按照字节对齐、2字节对齐方式。这个放在下一篇讨论。