C语言 结构体的大小和最小浪费空间
C语言 结构体的大小和最小浪费空间
因为内存对齐的问题,各个数据类型放的位置不同就会导致结构体的大小不一样,那么到底
怎样计算一个结构体的大小呢?
(最近在计算机系统课上发现的这个问题,只好重新拿起C语言)
许多计算机系统对基本数据类型的合法地址做出了一些限制,要求某种类型对象的地址必须是某个值K( 通常是2 、4 或8 )的倍数。这种对齐限制简化了形成处理器和内存系统之间接口的硬件设计。
类型 | K |
---|---|
char | 1 |
short | 2 |
int,float | 4 |
long,double,char* | 8 |
我们可以发现这个K值是和数据类型有关的(等于)。而这个K值有影响到后面的内存对齐。
当我们创建一个结构体:
typedef struct STRU{
char a;
short b;
double c;
char d;
float e;
char f;
long g;
int h;
}S;
创建结构体后,在内存中的情况为:
第一个数据a
为字符型大小为1
,K=2
,偏移应该为1的倍数,则偏移=0
(开始偏移为0);
第二个数据b
短整型大小为2
, K=2
,偏移应该为2的倍数,则偏移=2
;
第三个数据c
双精度小数型大小为8
, K=8
,偏移应该为8的倍数,则偏移=8
;
第四个数据d
字符型大小为1
, K=1
,偏移应该为1的倍数,则偏移=16
;
第五个数据e
单精度小数型大小为4
, K=4
,偏移应该为4的倍数,则偏移=20
;
第六个数据f
字符型大小为1
, K=1
,偏移应该为4的倍数,则偏移=24
;
第五个数据g
长整型大小为4
, K=4
,偏移应该为4的倍数,则偏移=28
;
第五个数据h
整型大小为4
, K=4
,偏移应该为4的倍数,则偏移=32
;
至此,内存上已经占用了36
个空间,由于结构体的大小必须为结构体成员中最大成员大小(这个结构体中为8)的倍数,则这个时候分配的空间大小应该为40
。
我们也可以用程序来验证:
#include <stdio.h>
int main ()
{
typedef struct STRU{
char a;
short b;
double c;
char d;
float e;
char f;
long g;
int h;
}S;
S A = {"a",2,3.1,"d",5.3,"f",777777777777,8};
printf("a in 0x%x\n",&(A.a));
printf("b in 0x%x\n",&(A.b));
printf("c in 0x%x\n",&(A.c));
printf("d in 0x%x\n",&(A.d));
printf("e in 0x%x\n",&(A.e));
printf("f in 0x%x\n",&(A.f));
printf("g in 0x%x\n",&(A.g));
printf("h in 0x%x\n",&(A.h));
printf("Size=%d",sizeof(T));
return 0;
}
输出结果:
a in 0x61fef8
b in 0x61fefa
c in 0x61ff00
d in 0x61ff08
e in 0x61ff0c
f in 0x61ff10
g in 0x61ff14
h in 0x61ff18
Size=40
为了更加直观的显示在内存的分布对齐情况可以查看下图(白色为浪费的空间,红色存放有数据):
)按照一些规律就可以很清楚的写出一个结构体的分布和对齐,下面是自己总结的一些简单的规律:
- 在内存上数据的偏移量与K有关(偏移量为K的倍数)。
- K的大小与数据类型有关 (数据类型大小=K,通常是2 、4 或8 )。
- 结构体的大小必须为结构体成员中最大成员大小的倍数。
根据图我们就可以发现,浪费的空间比较大,我们可以在结构体中按照数据大小降序来有效的节约空间、
#include <stdio.h>
int main ()
{
typedef struct STRU{
double c;
float e;
long g;
int h;
short b;
char a;
char d;
char f;
}S;
S A = {"a",2,3.1,"d",5.3,"f",77777777,8};
printf("c in 0x%x\t%d\n",&(A.c),sizeof(A.c));
printf("e in 0x%x\t%d\n",&(A.e),sizeof(A.e));
printf("g in 0x%x\t%d\n",&(A.g),sizeof(A.g));
printf("h in 0x%x\t%d\n",&(A.h),sizeof(A.h));
printf("b in 0x%x\t%d\n",&(A.b),sizeof(A.b));
printf("a in 0x%x\t%d\n",&(A.a),sizeof(A.a));
printf("d in 0x%x\t%d\n",&(A.d),sizeof(A.d));
printf("f in 0x%x\t%d\n",&(A.f),sizeof(A.f));
printf("Size=%d",sizeof(T));
return 0;
}
结果:
c in 0x61ff00 8
e in 0x61ff08 4
g in 0x61ff0c 4
h in 0x61ff10 4
b in 0x61ff14 2
a in 0x61ff16 1
d in 0x61ff17 1
f in 0x61ff18 1
Size=32