结构体为一堆相同或不同的数据类型的变量集合
结构体定义可看作一个模板(Template),而结构体变量可以看作是对这个模板的拷贝。
定义,声明
不带typedef
标签,变量,成员可选择性省略,一般至少包含两个
struct FFF//FFF为结构体标签,struct FFF为结构体数据类型名称,像int,long一样
{
int member_a;//三个结构体成员,可以是变量,指针,数组,甚至嵌套其他结构体
int member_b;
int member_c;
}FFF_A,FFF_B[3] = {{1,2,3},{11,22,33},{111,222,333}},*FFF_P;//声明三个结构体变量,可以是数组,变量,指针
struct FFF FFF_C;//另一种声明方法,如果省略结构体标签则不能用此方式声明
带typedef
typedef struct EEE//EEE为结构体标签
{
int member_1;
int member_2;
int member_3;
}EEE_A,EEE_B;//EEE_A,EEE_B为结构体的数据类型名称
EEE_A a;//只能这样创建结构体数据类型了。
调用
.是成员访问符,用于普通结构体变量的成员访问
->是类成员访问符,其左值一定为指针。
FFF_A.member_a = 22;//如果结构体变量就是一个普通变量的话就这样赋值 FFF_P = &FFF_A;//如果结构体变量为指针,那么他必须先有地址,否则p = 0x0 (*FFF_P).member_a = 33;//第一种方法:通过结构体指针变量访问的,这里要注意带括号否则.的优先级大于* FFF_P->member_a = 44;//第二种方法:通过结构体指针变量访问的 FFF_B[1].member_a = 8888; aaa.AAA.a = 3;结构体嵌套访问。
结构体变量
结构体变量可以是结构体普通变量,结构体变量数组,结构体指针变量
普通变量
如果是一个变量,那么这个变脸包含结构体的成员。
数组结构体变量
如果是一个数组,那么数组中的每个元素都包含结构体的成员。
结构体指针变量
如果是一个指针,那么这个指针的数据类型为该结构体,则指针的值只能为相同结构体的其他变量的地址。千万不要用直接使用结构体指针中的默认地址,当有多个结构体指针和共用体指针的话,尽管不在他们的TAG(标签)是不同的,也可能会出现问题。
结构体变量名
结构体变量名本身无实际意义,但是&结构体变量名是整个结构体变量的地址。这点和数组不同。
结构体内存存储
存储顺序原则
结构体变量成员的存储顺序是连续的,并按照结构体成员的定义顺序进行存储。
如写的顺序为int a,char b,int c,那么存放的顺序就是a,b,c。
字节对齐原则
当在内存中存放一个变量时,这个变量占用的字节数n必须被地址整除。如int的话n = 4,地址就是4的倍数。
也就是说从内存的第一个字节开始,每四个字节为一字,int形的变量必须对齐字的第一个字节。double必须对齐两字的第一个字节。
字节填充原则
如果结构体的最大变量为一个结构体存储单元,如果第一个变量比第二个变量小,那么变量必须字节对齐。那么结构体存储单元中其余空间就会被编译器填充。如果结构体存储单元为int,如第一个变量为char,第二个变量为int,那么中间就有三个填充就造成了浪费。那么如果存储单元是double,那么实际上一个int类型一个char类型就分别造成成了7个字节的浪费和4个字节的浪费。
所以,在配置结构体时,最好调整存储顺序从而减少填充。
结构体内存占用
结构体内存占用为最大变量的数据类型的n倍。且足够放下所有成员。
例如一个结构体成员为int a, char b char c[3]
那么结构体最小为int的2倍数,也就是8个字节。
共用体
共用体与结构体类似,关键字为union,但是共用体变量在一个时刻只能为一个成员的数据类型。
定义,声明
不带typedef
union FFF//FFF为结构公用体标签
{ double a;
int a;
char c;
}AA,BB[2],*CC;//公用体变量。可以是变量,数组,指针
union FFF DD;//另一种创建共用体变量的方式。
带typedef
typedef union FFF
{
double a;
int a;
char c;
}AA;
AA dd;
与结构体类似
共用体变量
共用体调用与结构体类似,但是一个时刻只能为一个变量的值。
普通变量
如果为普通变量,那么这个变量一个时刻只能为一个数据类型。
共用体数组变量
如果为数组,那么这个数组每个元素都是一个共用体变量
如果为指针,那么这个指针只能赋值给同一个副本下公用体的其他变量的地址。千万不要创建共用体指针后直接用,一定要赋值为其他共用体变量的值,否则会出问题。
共用体调用
共用体调用时,与结构体一样。都是使用(*a).member的方式或a->member。
共用体变量名
共用体变量名本身无实际意义,但是可以通过&来得到共用体地址以及*号可以访问。并sizeof中的是变量名而非&变量名。
结构体内存存储
最大的数据类型的倍数,可以满足单个的成员内存要求。如最大的类型为double = 8,但是数组最大为char a[12],那么结构体空间为两个double为16字节。