C语言-结构体+联合体+枚举

时间:2022-06-01 21:23:47
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//1、结构体:是一种构造数据类型
//结构体的用途:把不同的数据类型整合起来,成为一个自定义的数据类型

//1.1 定义一个结构体(定义结构体的关键字:struct)
//联想到Java中的类
// struct User{
// //年龄
// int age;
// //用户名
// char name[10];
// };

// int main(){
// //使用
// //第一种使用方式-构造初始化
// // 正确写法-初始化
// // struct User u = {18,"Dream"};
// // printf("%d, %s\n",u.age,u.name);
// //错误写法
// // struct User u;
// // u = {18,"Dream"};
// // printf("%d, %s\n",u.age,u.name);

// //第二种使用方式-成员赋值
// struct User u;
// u.age = 20;
// //错误写法
// //u.name = "Dream";
// //正确的写法
// strcpy(u.name,"Dream");
// printf("%d, %s\n",u.age,u.name);

// printf("Hello!");
// getchar();
// return 0;
// }


//1.2 第二种定义
// struct User{
// int age;
// char name[10];
// } u = {18,"Dream"},u1;

// int main(){
// printf("%d, %s\n",u.age,u.name);
// u.age = 100;
// strcpy(u.name,"Dream");
// printf("修改后:%d, %s\n",u.age,u.name);

// u1.age = 100;
// strcpy(u1.name,"Fantasy");
// printf("修改后:%d, %s\n",u1.age,u1.name);

// getchar();
// return 0;
// }


//1.3 第三种定义
// struct User{
// int age;
// char name[10];
// } u1,u2,u3;

// int main(){
// u1.age = 100;
// strcpy(u1.name,"Deram");
// printf("%d, %s\n",u1.age,u1.name);

// u2.age = 150;
// strcpy(u2.name,"微尘");
// printf("%d, %s\n",u2.age,u2.name);

// getchar();
// return 0;
// }

//1.4 第四种定义-结构体嵌套
//第一种写法-定义在外部
// struct Order{
// int count;
// char name[10];
// };
// struct User{
// int age;
// char name[10];
// Order order;
// };

//第二种写法-定义在内部
// struct User{
// int age;
// char name[10];
// struct Order{
// int count;
// char name[10];
// } order;
// };

// int main(){
// //构造方式赋值
// // struct User u = {18,"Dream",{999,"女装"}};
// // printf("User:%d, User:%s\n",u.age,u.name);
// // printf("Order:%d , Order:%s\n",u.order.count,u.order.name);

// struct User u;
// u.age = 100;
// strcpy(u.name,"Dream");
// u.order.count = 1000;
// strcpy(u.order.name,"男装");
// printf("User:%d, User:%s\n",u.age,u.name);
// printf("Order:%d , Order:%s\n",u.order.count,u.order.name);

// getchar();
// return 0;
// }


//1.5 第五种定义-匿名结构体:一般情况下,定义的同时至少有一个申明变量,否则没有什么意义
//好处:你可以控制结构体变量数量(限量版),一定程度上避免了出现结构体重名情况
//匿名结构体第一种写法
// struct{
// int age;
// double height;
// char name[10];
// } u1,u2;

// int main(){
// u1.age = 100;
// u1.height = 165.00;
// strcpy(u1.name,"Dream");
// printf("%d, %lf, %s\n",u1.age,u1.height,u1.name);
// return 0;
// }

//这种方式只有一个变量(单例)
//错误写法
// struct{
// int age;
// double height;
// char name[10];
// };

// int main(){

// age = 100;
// height = 165;
// strcpy(name,"Dream");
// printf("%d, %lf, %s\n",age,height,name);
// return 0;
// }

//1.6 第六种定义-结构体和数组
// struct User{
// int age;
// char name[10];
// } u1[2],u2[2] = {{18,"Dream"},{20,"迷离"}};

// int main(){
// //不能这么干
// //错误写法
// // u1[0] = {18,"Dream"};
// // u1[1] = {100,"Dream"};
// //正确写法
// // u1[0].age = 100;
// // strcpy(u1[0].name,"Dream");

// int i = 0;
// for(;i<2;i++){
// printf("%d, %s\n",u2[i].age,u2[i].name);
// }
// getchar();
// return 0;
// }

//结构体和指针
// struct User{
// int age;
// int height;
// char name[20];
// };

// int main(){
// // struct User u = {18,180,"石桥中画妖"};
// // //定义个结构体指针
// // struct User *p = &u;
// // //如何取值?
// // //printf("%d, %d, %s",(*p).age,(*p).height,(*p).name);
// // //(*p).age 等价于 p->age(简写)
// // //JDK 1.8里面也支持了这种写法
// // printf("%d, %d, %s",p->age,p->height,p->name);


// //数组
// struct User u1[] = {{18,175,"石桥中画妖"},{20,165,"Dream"}};
// //采用指针遍历数组
// struct User *p = u1;
// for(;p < u1 + 2 ; p++){
// printf("%d, %d, %s",p->age,p->height,p->name);
// }

// getchar();
// return 0;
// }


//结构体和内存(字节对齐)
//结构体在内存中也是一块区域(有顺序,线性排列)
// struct User{
// int age;
// double height;
// char name[20];
// // 4 + 8 + 12*2 = 36 36 % 8 = 0
// // 4 + 8 + 20 * 2 = 52%8? 53? 54? 55? 56%8=0
// };

// int main(){
// struct User u = {18,165};
// //打印结构体大小
// //int->4字节 double->8字节
// //按常理来说:12字节,但是结果却是:16字节
// //结构体字节对齐规则:
// //1.结构体变量的大小需要满足被最宽基本数据类型的成员大小所整出(int double float)
// //12%8?不成立 16%8=0成立
// //2.结构体变量的成员的首地址偏移量必须是最宽的基本数据类型的整数倍
// printf("大小: %lu\n",sizeof(u));

// //为什么C语言要这么设计?
// //初衷:就是为了提高读取效率(提高读取性能)
// //刘翔跨栏(110):每隔10米一个栏,如果每一个栏之间的距离不统一,那么跨栏难度系数会加大
// //遵循规律(节奏)
// getchar();
// return 0;
// }

//结构体和动态内存分配
// struct User{
// int age;
// double height;
// char name[10];
// };

// int main(){
// //数组(动态内存分配)-数组大小是3
// struct User *p = (struct User *)malloc(sizeof(struct User) * 3);

// //默认首地址
// // p->age = 100;
// // p->height = 160;
// // strcpy(p->name,"Dream");
// // printf("%d, %f, %s\n",p->age,p->height,p->name);

// // p++;
// // p->age = 20;
// // p->height = 165;
// // strcpy(p->name,"Dream");
// // printf("%d, %f, %s\n",p->age,p->height,p->name);

// //循环通过指针赋值
// int i = 0;
// for(;i<3;i++){
// p->age = 20+i;
// p->height = 165+i;
// strcpy(p->name,"Dream");
// printf("%d, %f, %s\n",p->age,p->height,p->name);
// p++;
// }

// getchar();
// return 0;
// }

//typedef 给结构体取别名(增强了可读性,简化了使用)
//第一种写法
// struct User{
// int age;
// double height;
// char name[10];
// };

// typedef struct User DreamUser;

//第二种写法
// typedef struct User{
// int age;
// double height;
// char name[10];
// } DreamUser,AgeUser;

// int main(){
// //使用方式(和Java基本上相同使用方式)
// DreamUser dream;
// dream.age = 18;
// dream.height = 165.00;
// strcpy(dream.name,"Dream");
// printf("%d, %f, %s\n",dream.age,dream.height,dream.name);

// getchar();
// return 0;
// }


//联合体(共同体:union关键字)
//作用:使多个不同类型的变量共用一块内存区域,联合体变量任何时候只有一个成员变量在内存中存在
//好处:节约内存
//总结:联合体分配内存大小
//联合体大小(在C语言中系统分配内存的机制)
//条件一:最大的成员字节大小
//条件二:还的是最大的成员的基本数据类型的字节数的整数倍

// union Student{
// int id;
// float height;
// char sex;

// char name[10];
// };

// int main(){
// //错误写法(不能直接初始化)
// //union Student stu = {10,"Dream"};
// //正确写法
// union Student stu;
// // strcpy(stu.name,"Dream");
// stu.id = 100;
// stu.sex = 'D';
// printf("%d\n , %c\n",stu.id,stu.sex);
// printf("%lu\n",sizeof(stu));
// //发现有什么问题?结果替换了

// getchar();

// return 0;
// }


//联合体-匿名联合体
//好处:你可以控制结构体变量数量(限量版),一定程度上避免了出现结构体重名情况
//第一种定义方式-匿名结构体
// union{
// int age;
// char name[10];
// } u;

// int main(){
// u.age = 100;
// getchar();
// return 0;
// }
//第二种方式
// static union{
// int age;
// char name[10];
// };

// int main(){

// age = 100;
// strcpy(name,"Dream");
// printf("%d\n",age);
// printf("%s\n",name);
// getchar();
// return 0;
// }

//方式三


// int main(){
// //其他方式调用:课后作业?
// union{
// int age;
// char name[10];
// };
// age = 100;
// strcpy(name,"Dream");
// printf("%d\n",age);
// printf("%s\n",name);
// getchar();
// return 0;
// }

//联合体取别名
// typedef union User{
// int age;
// char name[10];
// } DreamUser;

// union User{
// int age;
// char name[10];
// };
// typedef union User DreamUser;

// int main(){
// DreamUser dream;
// dream.age = 100;
// getchar();
// return 0;
// }

//枚举(定义:enum)---int类型
//总结:基本上和Java差不多
//好处:限定了值,保证取值的安全性
// enum MessageType{
// //文本类型
// Text = 10,
// //图片类型
// Image = 20,
// //文件类
// File = 30,
// //视频类型
// Video = 40,
// //语言
// Voice = 50
// };


// int main(){
// enum MessageType d = Text;
// printf("Text: %d\n",d);
// d = Image;
// printf("Image: %d\n",d);
// getchar();
// return 0;
// }

//枚举取别名
// typedef enum MessageType{
// //文本类型
// Text = 10,
// //图片类型
// Image = 20,
// //文件类
// File = 30,
// //视频类型
// Video = 40,
// //语言
// Voice = 50
// } Message;

// int main(){
// Message d = Text;
// printf("Text: %d\n",d);
// d = Image;
// printf("Image: %d\n",d);
// getchar();
// return 0;
// }



//匿名枚举
enum{
//文本类型
Text = 10,
//图片类型
Image = 20,
//文件类
File = 30,
//视频类型
Video = 40,
//语言
Voice = 50
} Message;

int main(){
Message = Text;
printf("Text: %d\n",Message);
Message = Image;
printf("Image: %d\n",Message);
getchar();
return 0;
}


整理自代码