首先,结构在C语言中也是一种数据类型,叫作聚组类型(还包括数组)。他和其余的数据类型是同样的,在定义一个结构体的时候,系统并不会为他真正的分配内存空间(定义的结构体变量要在编译的阶段才分配空间,而结构体指针要显示的使用malloca来分配空间),也就是说,在定义结构体这种数据类型的时候是不会分配内存空间的,只有在定义变量的时候,才会分配。web
下面是摘自百度百科 对结构题存储的三点:数组
1) 结构体变量的首地址可以被其最宽基本类型成员的大小所整除; 数据结构
2) 结构体每一个成员相对于结构体首地址的偏移量都是成员大小的整数倍,若有须要编译器会 在成员之间加上填充字节;ide
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,若有须要编译器会在最末一个成员以后加上填充字节spa
下面是来自《c和指针》的介绍指针
struct s1{code
char a;orm
int b;blog
char c;内存
};
首先,结构体在存储的时候,结构体的首地址必须可以被其中最宽数据类型整除。(在s1中,最宽数据类型为int,在32位系统中为4Byte),
其次,参照第二条,第一个数据时char(已经保证了,结构的起始地址是4的整数倍),存储一个char,占一个Byte,要保证下一个int的存储起始地址是4的整数倍,因此要在char后面填充三个Byte,而后在存储第三个数据。
第三,最后一个也是char类型,他就占一个Byte,确定是他存储位置的整数倍,最后参照第三条,结构体的总大小为最宽数据类型的整数倍,因此会在第二个char以后再填充三个Byte。
这样的话,总共占据的空间是1+3+4+1+3 = 12(红色为填充字符)
【可是】,调换一下结构中数据成员的顺序
struct s1{
int b;
char a;
char c;
};
一样地分析4+1+1+2 = 8
相比之下,存储空间的效率提升33%。
如下是系统对结构体的内存分配的详细介绍:
一、结构体变量的首地址是结构体中最宽数据类型的整数倍。
编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,而后寻找内存地址能是该基本数据类型的整倍的位置,做为结构体的首地址。
2、结构体每一个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,若有须要编译器会在成员之间加上填充字节。
为结构体的一个成员开辟空间以前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,如果,则存放本成员,反之,则在本成员和上一个成员之间填充必定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
三、结构体的总大小为结构体中最宽基本数据成员的整数倍。若有须要,编译器将会在结构体的添加填充字符。
四、结构体中的数据成员按照所占空间从大到小的顺序来排列的话,这样存储空间就会得以提升。
四、如今对四条进行修正。在组织数据结构的数据成员的时候,能够将相同类型的成员放在一块儿,这样就减小了编译器为了对齐而添加的填充字符。
【提示】:
有些时候,咱们不该该对结构的数据成员进行重排以减小因对齐带来的空间损失。由于在咱们对数据成员重拍的时候,每每破坏了数据间的关联性,从而下降了程序的可读性和可维护性。
综上,咱们能够得出,在对结构的成员进行重排的时候,即要考虑存储空间的使用效率,又要考虑程序的可读性与可维护性。
下面的代码是对上述几条的验证:
1 #include<stdio.h> 2 #include<stddef.h> 3 struct s1{ 4 int a; 5 char b; 6 char c; 7 }; 8 9 struct s2 { 10 char b; 11 char c; 12 int a; 13 14 }; 15 int main(){ 16 /* 17 struct s1 s; 18 s.a = 12; 19 s.b = 'a'; 20 s.c = 'b'; 21 22 printf("int s.a size: %d \n",offsetof(struct s1,a)); 23 printf("char s.b size: %d \n",offsetof(struct s1,b)); 24 printf("char s.b size: %d \n",offsetof(struct s1,c)); 25 printf("size of struct s1: %d\n",sizeof(struct s1)); 26 */ 27 28 29 struct s2 s; 30 s.a = 12; 31 s.b = 'a'; 32 s.c = 'b'; 33 34 printf("int s.a size: %d \n",offsetof(struct s2,a)); 35 printf("char s.b size: %d \n",offsetof(struct s2,b)); 36 printf("char s.b size: %d \n",offsetof(struct s2,c)); 37 printf("size of struct s1: %d\n",sizeof(struct s2)); 38 }