结构是一种由程序员自己设计的数据类型,用于描述一个事物的各项特征数据,由若干个不同的基础类型组成。
设计:
struct 结构体类型名
{
类型 成员名1;
类型 成员名2;
...
};
定义结构变量:
struct 结构体类型名 结构变量名;
注意:struct在c语言中,定义结构变量时不能省略
举例:
struct Student
{
// 设计学生结构类型
char name[20];
char sex;
char id[13];
double score;
};
int main()
{
// 定义一个学生结构变量
struct Student stu;
strcpy(stu.name,"hehe");
stu.sex = 'w';
strcpy(stu.id,"10086");
stu.score = 250.5;
scanf("%s",stu.name);
scanf("%lf",&stu.score);
printf("%s %c %s %lf",stu.name,stu.sex,stu.id,stu.score);
}
定义结构变量并初始化:
第一种方法:
struct 结构体类型名 结构变量名 = {v1, v2 ,v3...};
初始化顺序一定要与成员顺序一致
第二种方法:
struct 结构体类型名 结构变量名 = {.成员名2 = v2, .成员名1 = v1,...};
只初始化某些成员,顺序无需一致
注意:这种赋值方式只能在定义时使用
注意:同类型的结构变量可以直接给另一个结构变量初始化
例:
struct Student
{
char name[20];
char sex;
char id[13];
double score;
};
int main()
{
// 定义一个学生结构变量
struct Student stu = {.score=99,.id="8899"};
struct Student stu1 = stu;
}
访问成员:
结构变量名,成员名
由于结构变量的字节数一般都比较大,普通的值传递效率非常低,因此传递结构变量的地址,也即是传递结构指针变量,此时想要通过结构指针变量访问成员时借助 -> , 如果不需要修改指针变量的成员值,可以使用const保护
结构指针变量名->成员名;
结构体一般用typedef来重定义:
typedef 重定义结构类型名:
typedef struct 结构类型名 结构类型名;
typedef struct 结构类型名
{
}结构类型名;
注意:重定义之后,之后定义结构变量,可以不加struct
如何计算结构体的总字节数:
结构成员顺序影响它的的总字节数,如果能够在设计结构体时合理地安排成员顺序,可以大大地节约内存
内存对齐:
假设第一个成员从零地址开始,存储每个成员的地址编号必须能被该成员的类型字节数整除,如果不能整除则填充空白字节
内存补齐:
结构体总字节数必须是它最大成员字节数的整数倍,如果不能整除,则在末尾补充空白字节
在Linux系统下计算结构体的对齐和补齐时,如果成员的字节数超过4,则按照4字节计算对齐和补齐
windows是按实际字节数对齐补齐
例子:
char ch; 0 // 这是第一个成员,所以这是零地址
int in ; 4 // 0之后是1,1不能被int 的字节数4整除,所以加三个空白字节,int的地址从4开始
short a; 8 // 因为int占4个字节,所以此时到8,因为8是short的字节2 的倍数,所以直接从8开始
int b; 12 // 因为short占2个字节,所以此时到10,因为10不能int的字节4的倍数,所以加两个空白字节到12.
char c; 16 // 因为int占4个字节,所以此时到16,因为char的字节是1,所以此时是16
此时0~16是17个字节数,不能被最大成员字节数4整除,所以要加三个空白字节,到19
这样0~19一共20个字节。
成员的顺序不同会影响结构体的总字节数,如何顺序安排合理可以节约内存
#pragma pack(n) 可以设置对齐、补齐的最大字节数为n 但n <= 4 (1,2,4)
注意:结构体适合使用堆内存存储