C语言:构造类型(共用体/联合体,枚举)

共用体/联合体类型

定义

使几个不同的变量占用同一段内存的结构。共用体按定义中需要存储空间最大的成员来

分配存储单元,其他成员也是用该空间,他们的首地址是相同。

定义格式:

复制代码
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; // 4
    int b; // 4
    struct H h; // 8
};// 大小是16字节
// 共用体作为结构体成员
struct J
{
    int a;// 4
    char b;// 1 + 3
    union 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;
}
相关推荐
西元.2 分钟前
多线程循环打印
java·开发语言·jvm
高林雨露2 分钟前
Kotlin 基础语法解析
android·开发语言·kotlin
ml130185288749 分钟前
DeepSeek 助力心理医生小程序赋能!心理咨询小程序 线上咨询平台搭建
java·开发语言·小程序
不辉放弃9 分钟前
零基础讲解pandas
开发语言·python
用键盘当武器的秋刀鱼10 分钟前
springBoot统一响应类型3.5版本
java·spring boot·spring
A227411 分钟前
Netty——心跳监测机制
java·netty
犽戾武31 分钟前
浅谈多个虚拟机(WSL和VMWare)的网络配置
linux·网络
Heliotrope_Sun31 分钟前
测试用例篇
java·测试用例
tangweiguo0305198738 分钟前
(Kotlin)Android 高效底部导航方案:基于预定义 Menu 和 ViewPager2 的 Fragment 动态绑定实现
android·开发语言·kotlin
逊嘘39 分钟前
【MySQL】表的增删改查(拓展)
java·数据库·mysql