八、结构体、联合体、枚举
1.结构体
①. 概念:C语言描述复杂的对象,可以存放不同类型数据。
②. 模型:
struct 结构体的名字 { 成员属性1; 成员属性2; 成员属性3; 成员属性4; .... }; -->一定要加分 例子: struct student { char name[30]; unsigned char age; char sex; int num; }; 注意: student = {“lisi”, 18, ‘M’, 100}; //数据类型是不可以赋值的 struct student= {“lisi”, 18, ‘M’, 100};//数据类型是不可以赋值的 struct student lisi = {“lisi”, 18, ‘M’, 100}; //正确用法:定义变量,申请了空间,才可以赋值。
③. 定义结构体变量-->是为了申请内存
1》全部初始化赋值1 struct student lisi= {“lisi”, 18, ‘M’, 100}; 2》全部初始化赋值2 struct student lisi={.name="lisi", .age=18, .sex='M', .num=180}; struct student lisi={ .age=18, .name="lisi", .sex='M', .num=180}; 3》部分初始化赋值3 struct student lisi={ .age=18, .num=180}; 4》非初始化赋值 struct student lisi; lisi.name = "lisi"; //数组非初始化赋值不能直接用数组名赋值为字符串 //相当于:char buf[20]; buf = “hello”; 不行,因为语法不支持 strcpy(lisi.name, "lisi"); //数组非初始化赋值可以用strcpy lisi.age = 18; lisi.sex = 'M'; lisi.high = 180;
④. 结构体大小
地址对齐:计算机为了提高访问结构体成员效率 在32位系统里面,最大地址对齐字节数是4个字节 在64位系统里面,最大地址对齐字节数是8个字节 确定结构体类型的大小: 1》先找出所占字节数最大成员,以他的字节数作为地址对齐字节数, 在32位系统里面如果地址对齐字节数超出4个字节,是以4个字节作为地址对齐的单位 在64位系统里面如果地址对齐字节数超出8个字节,是以8个字节作为地址对齐的单位 2》数组是以元素的类型作为地址对齐的单位 3》定义结构体成员时,可以尽量按照从小到大进行排列 4》结构体大小可能需要考虑二次地址对齐
⑤. 结构体数组
结构体数据类型+变量名[元素个数]; //1、定义学生结构体类型 struct student { char name[20]; char sex; unsigned char age; unsigned int num; }; //2、定义结构体数组 struct student info[10]; bzero(info, sizeof(info)); //3、给数组成员赋值
⑥. 结构体指针
//1、定义学生结构体类型 struct student { char name[20]; char sex; unsigned char age; unsigned int num; }; 2、定义变量 struct student lisi; 3、定义结构体指针(一定要存储变量的内存地址后,才能解引用使用) struct student *p = &lisi; //p==&lisi //lisi.name = "lisi"; //数组非初始化赋值不能直接用数组名赋值为字符串 strcpy(lisi.name, "lisi"); lisi.age = 18; lisi.sex = 'M'; lisi.num = 100; strcpy((*p).name, "lisi"); (*p).age = 18; (*p).sex = 'M'; (*p).num = 100; strcpy(p->name, "lisi"); //p->name == (*p).name == (*(&lisi)).name ==lisi.name == (&lisi)->name p->age = 18; //p-> age == (*p). age == (*(&lisi)). age ==lisi. age == (&lisi)-> age //p->age 不是表示age的地址,表示的是p这个地址里面的结构体成员age //&(p->age ) 才是表示p这个地址里面的结构体成员age的地址 p->sex = 'M'; //p-> sex == (*p). sex == (*(&lisi)). sex ==lisi. sex == (&lisi)-> sex p->num = 100; 注意: 1》怎么去定义结构体指针,然后存储结构体变量地址 2》怎么通过结构体指针访问结构体成员和获取结构体变量成员地址 3》通过结构体地址(指针)访问结构体成员的方式: (*p).name == p->name == (&lisi)->name == lisi.name (*p).age == p->age == (&lisi)->age == lisi.age age的地址表示方式: &(*p).age == &p->age == &(&lisi)->age == &lisi.age 4》一定要注意: p->age 表示是结构体成员变量age的值,不是表示它的地址 它的地址表示方式: &p->age 5》结构体变量的值可以整体赋值给另外一个结构体变量 #include <stdio.h> #include <strings.h> #include <string.h> //1、定义学生结构体类型 struct student { char name[20]; char sex; unsigned char age; unsigned int num; }; int main(int argc, const char*argv[]) { struct student lisi={"lisi", 'M', 18, 101}; struct student xiaoming; bzero(&xiaoming, sizeof(xiaoming)); xiaoming = lisi; /* strcpy(xiaoming.name, lisi.name); xiaoming.sex = lisi.sex; xiaoming.age = lisi.age; xiaoming.num = lisi.num; */ printf("xiaoming信息:\n"); printf("name:%s\n", xiaoming.name); printf("sex:%c\n", xiaoming.sex); printf("age:%hhu\n", xiaoming.age); printf("num:%d\n\n", xiaoming.num); printf("lisi信息:\n"); printf("name:%s\n", lisi.name); printf("sex:%c\n", lisi.sex); printf("age:%hhu\n", lisi.age); printf("num:%d\n", lisi.num); return 0; } 6》可以直接在定义结构体数据类型时,定义结构体变量 #include <stdio.h> #include <strings.h> #include <string.h> //1、定义学生结构体类型 struct student { char name[20]; char sex; unsigned char age; unsigned int num; }lisi; //顺便定义了一个结构体全局变量lisi int main(int argc, const char*argv[]) { struct student lisi={"lisi", 'M', 18, 101}; printf("lisi信息:\n"); printf("name:%s\n", lisi.name); printf("sex:%c\n", lisi.sex); printf("age:%hhu\n", lisi.age); printf("num:%d\n", lisi.num); return 0; }
⑦. 结构体嵌套
//0、定义一个成绩结构体 struct score { int Chinese; int Math; int PE; }; //1、定义学生结构体类型 struct student { char name[20]; char sex; unsigned char age; unsigned int num; struct score myscore; //定义表示成绩的成员 }; //2、定义结构体变量 struct student lisi; bzero(&lisi, sizeof(lisi)) //3、给它成员赋值 strcpy(lisi.name, "lisi"); lisi.age = 18; lisi.sex = 'M'; lisi.num = 180; lisi.myscore.Chinese = 99; //访问结构体里面的结构体成员 lisi.myscore.Math = 100; lisi.myscore.PE = 90;
2.联合体
①. 概念:联合体成员共用一块内存,使用时,在成员选择一个
②. 定义联合体数据类型
union 联合体名字 { 成员属性1; 成员属性2; 成员属性3; .... };
③. 联合体的内存大小
最大成员所占字节数就是它的内存大小 union sore { int a; short b; char c; double d; }; union sore mysore; printf("%d\n", sizeof(mysore)); //8个字节--》double最大(八个字节)
④. 联合体成员不能混用--》最好选择其中一个成员使用,否则会出现数据混乱
⑤. 通过联合体判断主机字节序
主机字节序:计算机存储数据的顺序
小端序:低位数据存储到低位地址,高位数据存储到高位地址 大端序:高位数据存储到低位地址,低位数据存储到高位地址
3. 枚举 --》自定义数据类型--》本质表示定义多个无符号整型数
enum num { a, b, c, d, e, }; 等价于定义了5个unsigned int类型变量 unsigned int a=0, b=1, c=2, d=3, e=4; 注意:1》定义枚举类型就是表示定义多个无符号整型数,不需要定义枚举变量就可以直接使用