c语言允许有自定义的类型
结构体--struct
枚举--enum
联合体--union
1.结构体类型的声明
1.1结构体
结构体是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如: 标量、数组、指针,甚⾄是其他结构体
1.1.1结构的声明
例如描述一个学生
- struct book
- {
- char name[20];//名字
- char author[20];//作者
- float price;//价格
- char id[13];//图书号
- }; //分号不能丢
1.1.2结构体变量的创建和初始化
创建结构体变量的三种情况,类似于整形变量和字符型变量的创建,结构体变量就是结构体类型+变量名
初始化
#include<stdio.h>
struct book
{
char name[20];
char author[20];
float price;
char id[13];
};
int main()
{
//按照结构体成员的顺序初始化
struct book b1 = {"c语言笔记","芋泥",33.3,"23063564"};
//按照指定的顺序初始化
struct book b2 = { .id = "23063564",.author = "芋泥",.name = "c语言笔记",.price = 33.3 };
return 0;
}
结构体嵌套初始化
struct s1
{
int x;
int y;
};struct s2
{
int z;
struct s1 b1;
struct s2* b2;
}n1 = { 4,{2,3} ,NULL};
1.1.3结构的特殊声明
匿名结构体,就是结构在声明的时候省略掉了结构体标签
- 匿名结构体的错误初始化方式
- 正确的初始化
这也说明匿名结构体只能使用一次
- 观察改代码是否合理
struct
{
int x;
int y;
}s;
struct
{
int x;
int y;
}*ps;
int main()
{
ps = &s;
return 0;
}
这段代码是不合理的,s是匿名结构体,无法判断ps和s的类型相同,编译器会把上⾯的两个声明当成完全不同的两个类型,所以是非法的。。"=";从" * "到" * "的类型不兼容
- 注意
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使用一次。
1.2 结构成员访问操作符
1.2.1结构体成员的直接访问
- 结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数。如下所示:
struct s1
{
int x;
int y;
}s = {2,3};int main()
{
printf("%d %d ", s.x, s.y);
return 0;
}
使用方式:结构体变量.成员名
1.2.2结构体成员的间接访问
有时候我们得到的不是一个结构体变量,而是得到了一个指向结构体的指针
struct s1
{
int x;
int y;
};int main()
{
struct s1 s = {2,3};
struct s1* ps = &s;
printf("x=%d y=%d\n", ps->x, ps->y);
ps->x = 5;
ps->y = 6;
printf("x=%d y=%d\n", ps->x, ps->y);
return 0;
}
使用方式:结构体指针->成员名
1.3结构体的自引用
- 链表节点的定义
struct Nod
{
int x;
struct Nod y;
};
上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?
仔细分析,其实是不行的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的大小就会无穷的大,是不合理的。
- 正确的自引用方式
struct Nod
{
int x;
struct Nod *y;
};
- typedef 对结构体类型重命名
struct Nod
{
int x;
struct Nod *y;
};
typedef struct Nod Nod;int main()
{
Nod s;
return 0;
}
在结构体自引用使用的过程中,夹杂了 typedef 对匿名结构体类型重命名,也容易引⼊问题,看看 下⾯的代码,可行吗?
typedef struct
{
int x;
Nod *y;
}Nod;
结构体内部的成员是先被创建好的,typede将结构体类型重命名是后来的操作
Node是对前面的匿名结构体类型的重命名产生的,但是在匿名结构体内部提前使用Node类型来创建成员变量,这是不行的。
2.结构体内存对齐
就是求结构体的大小
首先要掌握结构体的对齐规则