构造数据类型
构造数据类型一、结构体1.定义把多个数据类型包含基本数据类型和构造数据类型组合在一起描述一个相对复杂的事物(个体)2.定义结构体结构体的声明 struct 结构体名 { 具体的属性值1; 具体的属性值2; 具体的属性值3; 具体的属性值4; 具体的属性值5; } // 分号不可省略 // 只是声明不开辟内存空间。 struct Date { int year; int mon; int day; } struct Person { char name[50]; int age; int heigh; char phone[20]; struct Date date; };3.定义结构体变量//struct 结构体名 变量名 //开辟内存空间 struct Person per2; struct Person *point per24.结构体成员的访问(1)运算符. 双目运算符 从左到右 1级优先级- 双目运算符 从左到右 1级优先级何时使用 . 或 - , 取决于运算符的的左操作数。左操作数是变量使用. 。如果是指针使用-2访问成员访问成员的时候如果是通过变量访问 使用. 运算符访问成员的时候如果是通过指针访问 使用-运算符per2 是变量的情况per2.name表达式的类型是 name 的数据类型 。当使用访问运算符访问后表达式的类型 由右操作数决定per2 是指针的情况per2-name表达式的类型是name 的数据类型 。当使用访问运算符访问后表达式的类型 由右操作数决定5.结构体的大小字节对齐问题 默认 4字节对齐当结构体声明好 系统会对结构内存空间布局进行调整。提高cpu 读写内存的效率。1需要存储变量的地址值和该类型的大小 进行求余操作。如果余数为0 。则该变量储存在这个地址。如果不是地址加1后继续求余。2找到结构体中占用空间最大的成员(基本数据类型的成员 4byte/8byte) 。 最终结构体的大小是4的倍数或8的倍数。例如struct Person { char name[50]; //50 int age; //4 float heigh; //4 char phone[20]; //20 };经过字节对齐后结构体大小为80byte6.结构体传参1值传递void fun(struct Person per){} //对结构体的数据成员操作 只能进行读取操作劣势 由于是值传递所以在被调函数中需要对实参进行整体复制。 函数调用完毕后形参空间需要释放。如果结构体占用内存空间很多的话。效率就很低2地址传递void fill_per(struct Person* p{}地址传递 内存使用效率高。 因为任意指针都是8个字节。在被调函数中如果只需要读取数据的话加const 修饰指针就可以了。 如果需要读写的话去掉const再进行修改。二、结构体数组1.定义struct 结构体名 数组名[整形常量]strcut Person array[10];2.初始化//全部清 0 struct Person array[5]{0}; // 全部初始化 struct Person array2[3]{ {zhangsan,10,{2026,05,10}}, {lisi,11,{2025,03,12}}, {wangmaizi,12,{2024,01,22}}, }; // gcc 支持的初始化方式 struct Person array3[3] { [1]{zhangsan,20,{2021,10,1}}, };3.访问void show_pers(const struct Person arrar[],int size) { int i 0 ; for(i0;isize;i) { show_per(arrar[i]); //下标方式访问 } } int main(int argc, char **argv) { //全部清 0 struct Person array[5]{0}; // 全部初始化 struct Person array2[3]{ {zhangsan,10,{2026,05,10}}, {lisi,11,{2025,03,12}}, {wangmaizi,12,{2024,01,22}}, }; / printf(array3 name:%s y:%d m:%d d:%d\n,array3[1].name,array[1].date.year,array[1].date.mon ,array[1].date.day); ////下标方式访问 show_pers(array2,3); return 0; }4.typedef 和structstruct Person { char name[50]; int id; }; typedef unsigned char u8; typedef int* (*PFUN)(int, int); //函数指针类型 typedef struct Person1 { char name[50]; int id; } PER; // PER struct Person1 int main(int argc, char** argv) { struct Person per {0}; PER per2 {zhangsan, 20}; struct Person1 per3 {lisi, 10}; printf(name:%s id:%d\n, per2.name, per2.id); return 0; }三、共用体联合体1.定义定义共用体也叫联合体。和结构体的定义初始化访问元素都一样的。只有一处差异开辟内存空间有差异。在结构体中每个成员都是要开辟内存空间的字节对齐问题。共用体中 开辟空间的大小是最大成员的大小。所有的成员共享一份内存。2.应用需要节省内存空间的情况 如果可以使用结构体或联合体作为函数参数传递的时候如果参数本身有多个选项的时候所有的选项以联合体形式给出(多选1)。可以判断大小端3.语法定义union 共用体类型名 { 数据成员1; 数据成员2; 数据成员3; ... }; // 分号不可省4.初始化和访问union TestAAA { int a; char b; long d; }; int main(int argc, char **argv) { //清零 union TestAAA test{0}; //访问 test.a 300; printf(a is %d\n,test.a); printf(b is %d\n,test.b); printf(b is %ld\n,test.d); test.d 123132300; // 会覆盖原来 test.a 中值 内存只有一份。 return 0; }5.大小端判断//大小端判断 union End { int ia; char cc; }; int main(int argc, char **argv) { union End end {0}; end.ia 1; printf(union size is %lu\n,sizeof(union End )); if (1 end.cc) { printf(小端\n); } else { printf(大端\n); } return 0; }四、枚举1.定义定义一个自定义的变量把变量可以取到所有的值一一列举出(或者说一个取值的范围)来。枚举值在c语言中当 整形(int)常量数据看2.声明enum 枚举类型名 {枚举值1,枚举值2枚举值3,枚举值4.....} 枚举值 默认从0 开始后面的只都是依次1 // MON 0 1 2 3 4 5 6 enum WEEK {MON,TUE,WED,THU,FRI,SAT,SUN}; 枚举值 用户可以指定初值。 //3 4 5 6 7 8 9 enum WEEK1 {MON13,TUE1,WED1,THU1,FRI1,SAT3.定义变量enum WEEK week THU; // week 1000; 枚举这个类型c语言中 当整形变量对待。不建议这么写。 switch(week) { case MON: printf(go to school\n); break; case FRI: printf(to play...\n); break; case SUN: printf(go to sleep\n); break; default: printf(发呆\n); }