格式:typedef 数据类型 别名;
typedef和数据类型结合
typedef int size_4 size_4是int的别名,size_4--->int
typedef int arr_t[3] arr_t是int [3]的类型别名 int a[3] --->arr_t b;
typedef int d_arr_t[2][3] d_arr_t---->int [2][3]
typedef int a, *p, arr[3];
a--->int
p---->int*
arr--->int [3]
typedef int size_4
#define size_4 int ---> size_4 --->int
1.typedef属于类型重定义,define宏替换
2.typedef属于C语句,define不属于C语句
3.typedef发生在编译阶段,define发生在预处理阶段
4.typedef可以重定义任何复杂的数据类型,define只可以替换基类型
引入目的:数组存储类型相同的数据元素,需要存储类型不同的内容则组要借助于结构体
结构体:用来存储多个类型相同或不同的构造类型
构造类型:数组,结构体,共用体
格式: struct 结构体名
{ 数据类型 成员变量1;
数据类型 成员变量1;
数据类型 成员变量1;
....
};
{ } ; 不可以省略
结构体描述,计算机不分配内存,直到存在结构体变量
结构体描述一般写在全局
间接引用
struct Person
{ char name[20];
int blood;
int magic;
char color[20];
};
struct Person a;
struct Person a={"aaa",4,10,"红"};
输入赋值
struct Person d;
scanf("%s",d.name); // d.name--->name
scanf("%d",&d.blood);
scanf("%d",&d.magic);
scanf("%s",d.color);
struct Car
{ char name[10];
int price;
char color[10];
};
struct Car a[2];
按顺序初始化 struct Car a[2]={{"凤凰",250,"黑"},{"小刀",1200,"绿"}}; struct Car a[2]={"凤凰",250,"黑","小刀",1200,"绿"}; struct Car a[]={"凤凰",250,"黑","小刀",1200,"绿"};
循环输入赋值 struct Car d[2]; for(int i=0;i<2;i++) { scanf("%s",d[i].name); scanf("%d",&d[i].price); scanf("%s",d[i].color); }
struct Car { char name[10]; int price; char color[10]; };
结构体指针指向普通结构体变量的地址
struct Car a={"凤凰",250,"黑"};
struct Car *p=&a;
结构体指针指向结构体数组的地址
struct Car a[2]={"凤凰",250,小刀",2000};
struct Car *p=a;
for(int i=0;i<3;i++) { printf("%s %d",(p+i)->name,(p+i)->price); printf("%s %d",(*(p+i)).name,(*(p+i)).price); }
结构指针执行堆区首地址 (重点)
int *p=(int *)malloc(sizeof(int)*n) struct Car *p=(struct Car *)malloc(sizeof(struct Car)*2); for(int i=0;i<3;i++) { printf("%s %d",(p+i)->name,(p+i)->price); printf("%s %d",(*(p+i)).name,(*(p+i)).price); }
1.结构体成员不可以直接使用
2.普通结构需要使用结构变量加 . 引用
3.结构体数组需要使用.引用
格式:数组名[index].成员
4,.结构体指针的引用,使用->
格式:指针变量名->成员
5.值使用.引用,地址使用->引用
6.结构体变量的含义,多使用传参和返回
struct Car a={"凤凰",250,"黑"};
struct Car b={"11",250,"红"};
a.name
a.price
a.color
a --->表示结构体的所有信息
结构体嵌套
结构体嵌套结构体数组
结构体嵌套动行为
1.结构体变量的首地址就是第一个成员的地址
2.结构体的各个成员的地址连续
3.结构体的总字节大小是各个成员字节的总和
64为操作系统:属于8字节对齐
满足字节对齐:
i> 结构体的总字节,必须是最宽成员的倍数,否则使用空字节填充
ii> 结构体的首地址,必须被最宽成员的倍数
iii> 结构体各个成员的偏移量,是各个成员字节的倍数,否则使用空字节填充
32为操作系统:属于4字节对齐
满足字节对齐:
i> 结构体的总字节,必须是最宽成员的倍数,否则使用空字节填充
如果最宽成员是1,则是1的倍数
如果最宽成员是2:则是2的倍数
如果最宽成员是4,8:则是4的倍数
ii> 结构体的首地址,必须被最宽成员的倍数
iii> 结构体各个成员的偏移量,是各个成员字节的倍数,否则使用空字节填充
如果成员是1字节,则偏移量是1的倍数
如果成员是2字节,则偏移量是2的倍数
如果成员是4,8字节,则偏移量是4的倍数
结构体位域:是把内存大小扣到极致的一种结构体
定义格式:
struct 位域体名
{
数据类型 位域名:位域大小; ....
};
struct AA { int a:10; int b:5; int c:5; };
struct AA
{ int a:10; // -2^9 ------2^9-1 long d:50; // -2^49 ----2^49-1 unsigned char b:8; // 0----2^8-1 short c:15; // -2^14 ---2^14-1 };
struct AA num={10,20,30,40};
head.h
main.c
test.c