结构体:是一系列有相同类型或不同类型构的数据构成的数据集合。
结构体的学习可以从以下几个方面开始:
一.结构体类型的声明。
struct tag{
member-list;
} vaeriable-list;
注:tag 要做到见名知义,可以省略但是不建议省略
member-list 不能为空
veriable-list 建议省略(在需要的时候在声明)
例如建造一个学生的结构体
struct s{
int math;
int chinese;
};
struct stu{
char name[20];
int age;
struct s score;//结构体的嵌套
};
匿名结构体:声明结构体的时候可以省略tag,即为匿名结构体。
struct{
int a;
int b;
char c;
} x;
注:即使两个结构体的数据类型完全相同,他们也是两个结构体。
二.结构体的成员。
结构体成员的访问:
1. stu.name;
stu.age;
2.struct stu stu1;
struct stu* p=&stu;
(*p).name;
(*p).age;
p->name;
p->age;
三.结构体的自引用。
在结构体中不可以包含一个类型为他自身的结构体。
但结构体中可以包含自身类型的指针类型。
如:
struct Node{
int data;
struct Node* next;
};
四.结构体的不完整声明。
struct A{
int _a;
struct B*p1;
};
struct B {
int _b;
struct A*p2;
};
四.结构体变量的定义和初始化。
定义:struct s score1;
初始化 struct s score2={88,90};4
结构体的嵌套初始化:struct stu stu1={"zhang",18,{88,90}};
结构体的赋值只能访问成员变量逐个赋值,不可以一起赋值。
六.结构体的内存对齐。
现象:
#include<stdio.h>
#include<Windows.h>
struct s1{
int a;
char c;
double d;
};
struct s2{
char c;
double d;
int a;
};
int main(){
printf("%d\n", sizeof(struct s1));
printf("%d\n", sizeof(struct s2));
system("pause");
return 0;
}
上面一段简单的代码我们希望的打印结果是:13 13
但实际确实如下:
为什么会出现以上现象呢?这就是结构体的内存对齐。
结构体内存对齐的原因:主要有平台和性能两个原因,简而言之,就是拿空间换取时间。
对齐规则:
1.第一个成员在与结构体变量的偏移量为0的地指出;
2.下一个成员变量对齐到该成员变量的对齐数的整数倍地址处。对齐数=min(默认对齐数(vs:8,liunux:4),该成员字节数);
3.结构体的总大小为所有成员变量的最大的对齐数的整数倍;
4.如果结构体嵌套,嵌套的结构体对齐到自己最大对齐数的整数倍除,结构体的整体大小就是所有成员变量最大的对齐数的整数倍。
例子:
#include<stdio.h>
#include<Windows.h>
struct s1{
int a;//4
char c;//4+1=5;
double d;5+3+8=16
};//16可以整除最大对齐数8,故s1=16
struct s2{
char c;// 1
struct s1 s;1+7+16=24
double d;//24+8=32
int a;//32+4=36
};大于36的最小的整除最大对齐数8的是40,所以运算结果应该是40
int main(){
printf("%d\n", sizeof(struct s2));
system("pause");
return 0;
}
七.传参。
结构体传参有传值和传址两种,均会形成临时变量,在结构体成员很多时传址的效率高于传值。
void print1(struct s2 s){
//传值
printf("%d\n", s.a);
}
void print2(struct s2*p){
//传址
printf("%d\n", p->a);
printf("%d\n", (*p).c);
}