共用体/联合体类型
定义
使几个不同的变量占用同一段内存的结构。共用体按定义中需要存储空间最大的成员来
分配存储单元,其他成员也是用该空间,他们的首地址是相同。
定义格式:
union 共用体名称
{数据类型 变量名; -- 共用体成员数据类型 变量名;...
};
公用体的定义和结构体类似:
可以有名字,也可以匿名
共用体在定义时也可以定义公用体变量
共用体在定义时也可以初始化成员
共用体也可以作为形参和返回值类型使用
共用体也可以定义共用体变量
...
也就是说,结构体的语法,共用体都支持
注意:
共用体弊大于利,尽量少用,一般很少用;
共用体变量在某一时刻只能存一个数据,并且也只能取出一个数
共用体和结构体都是自定义数据类型,用法类似于基本数据类型
共用体可以是共用体的成员,也可以是结构体的成员
结构体可以是结构体的成员,也可以是共用体的成员
案例:
/*** 共用体*/
#include <stdio.h>
// 定义共用体
union S
{char a;float b;int c;
};// 大小是4字节
// 共用体作为共用体的成员
union F
{char a;union S s; // 4字节
};// 大小是4字节
// 共用体作为结构体的成员
struct G
{int a;union S s;
};// 大小是8字节
// 定义一个结构体
struct H
{int a;char b;
};// 大小是8字节
// 结构体作为结构体成员
struct I
{int a; // 4int b; // 4struct H h; // 8
};// 大小是16字节
// 共用体作为结构体成员
struct J
{int a;// 4char b;// 1 + 3union S s;// 4
};// 大小是12字节
void test1()
{
// 定义共用体类型union Stu{int num;char sex;double score;};// 定义匿名共用体:匿名共用体一般作为结构体成员或者其他共用体成员union{int a;char c;} c;printf("%lu,%lu\n",sizeof(union Stu),sizeof(c));
}
void test2()
{union C{int a;char b;};// 定义变量union C c; // 存数据c.a = 10;c.b = 'A';printf("%d---%d\n",c.a,c.b);// 取数据c.a += 5;printf("%d---%d\n",c.a,c.b);// 取数据union E{char *f;long a;int b;} e = {"hello world!"};printf("%s,%p---%ld,%p---%d\n",e.f,&(e.f),e.a,&(e.a),e.b);
}
int main()
{test1();test2();
}
枚举类型
定义
我们一般情况下,定义常量使用宏定义(#define 红名称值),宏定义非常适合没有关联关系的
常量;但是有时候我们可能需要对一组拥有关联关系的量进行定义,比如 ==周一~周日、1月~12
月、方向(上下左右中)等 ,那么使用宏定义,就不是很清晰,这个时候就需要使用到枚举。
枚举的存在就是将多个拥有关系的常量组合到一起,提高代码的可读性。
说明:
枚举类型定义了一组常量,我们在开发中直接使用这些常量。(常用)
当然枚举类型也可以类似于结构体一样定义变量等操作。(不常用)
枚举常量有默认值,从0开始依次+1;我们可以在定义时指定它的默认值,如果个别没有赋值,
可以根据赋值依次+1推导。
特点:
定义了一组常量,类似于定义了多个自定义常量(宏定义)
提供了代码的可读性。
定义语法:
定义枚举类型名以后就可以定义该枚举类型的变量。
enum 枚举类型名 变量列表;
在定义枚举类型的同时定义该枚举类型的变量。
enum 枚举类型名{枚举元素列表} 变量列表;
直接定义枚举变量
enum {枚举元素列表} 变量列表;
案例:
#include <stdio.h>
void test1()
{// 定义一个枚举类型// 枚举类型名一般首字母大写,主要是根枚举变量区分enum Week {// 定义枚举元素,元素命名要符合标识符命名规则,同时采用大写字母+下划线方式命名SUN=10,MON,TUE,WED,THU,FRI,SAT};// 1.直接访问枚举元素printf("%d,%d,%d\n",SUN,WED,SAT);// 2.定义枚举类型的变量(先定义变量,后赋值)enum Week week;// 初始化week = TUE;// 一定是这个枚举类型中定义的元素printf("%d\n",week);// 3.定义枚举类型变量的同时赋值(定义变量和赋值同时进行)enum Week week1 = THU;printf("%d\n",week1);enum H{A,B,C // 多个元素使用逗号分隔
} x,y;x = B;y = C;printf("x=%d,y=%d\n",x,y);// 1,2
}
void test2()
{// 定义枚举enum CaiQuan{SHI_TOU,JIAN_DAO,BU};printf("请输入0~2之间的整数:\n[0-石头,1-剪刀,2-布]\n");int number;scanf("%d",&number);switch(number){case SHI_TOU:printf("石头\n");break;case JIAN_DAO:printf("剪刀\n");break;case BU:printf("布\n");break;}
}
int main(int argc,char *argv[])
{test1();test2();return 0;
}
typedef
说明:给类型重命名,不会影响到类型本身
作用:给已有的类型起别名
格式:
typedef 已有类型名 新别名;
使用:
// 方式1:先定义结构体类型,再重命名
// 定义一个结构体类型
struct Student
{int id;char *name;char sex;int age;
};
// 类型重命名
typedef struct Student Stu;
// 定义结构体变量
struct Stu stu = {1,"张三",'w',21};
// 方式2:定义结构体的同时重命名
typedef struct PersonInfo
{int a;double b;
} Per; // 结构体类型的别名,本质上还是数据类型
// 定义变量
struct Per per = {2,5};
应用场景:
数据类型复杂(结构体、共用体、枚举、结构体指针、无符号的长整型)时使用
为了跨平台兼容性,例如:
1. size_t:类型重命名后的数据类型: typedef unsigned long size_t;
2. unit_16:类型重命名后数据类型
案例:
//类型重命名
#include <stdio.h>
struct Student
{int age;char* name;double score;int arr[3];
};
typedef struct Student Stu_t;// 数据类型重命名
typedef Stu_t* pStu_t;// 结构体指针重命名
void test1()
{Stu_t s1 = {23, "zhangsan", 23.33, {11, 22, 33}};printf("%d, %s, %f, %d\n", s1.age, s1.name, s1.score, s1.arr[0]);//Stu_t *p = &s1;Stu_t* p;p = &s1;pStu_t p2;p2 = p;printf("%d, %s, %f, %d\n", p2->age, p2->name, p2->score, p2->arr[0]);}
int main()
{test1();return 0;
}