【C语言】自定义类型:联合和枚举

前言

前面我们学习了一种自定义类型,结构体,现在我们学习另外两种自定义类型,联合枚举

目录

一、联合体

  1. 联合体类型的声明

  2. 联合体的特点

  3. 相同成员联合体和结构体对比

  4. 联合体大小的计算

  5. 用联合体判断当前机器大小端

二、枚举

  1. 枚举类型的声明

  2. 枚举类型的优点

  3. 枚举类型的使用


正文开始------

一、联合体

1. 联合体类型的声明

与结构体一样,联合体是由一个或多个成员构成,这些成员可以是不同的类型。

cs 复制代码
   #include<stdio.h>
  
   //联合体类型的声明  union是关键字
   union Un
  {
      char c;
      int i;
  };
    
   int main()
  {
     //联合体变量的定义
     union Un un={0};
     //计算联合体变量的大小
     printf("%zd\n",sizeof(un));

   return 0;
  }

2. 联合体类型的特点

联合的成员是共用一块内存空间的(所以联合体也叫共用体),所以联合变量的大小至少是最大成员的大小,因为联合体至少得有能力保存最大的那个成员。

代码 1 及其运行结果

cs 复制代码
   #include<stdio.h>
   //联合类型的声明
   union Un 
  {
     char c;
     int i;
  };
   
   int main()
 {
   union Un un={0};
   printf("%p\n",&(un.c));
   printf("%p\n",&(un.i));
   printf("%p\n",&un);
   return 0;
 }

代码 2 及其运行结果

cs 复制代码
   #include<stdio.h>
   //联合类型的声明

   union Un
  {
         char c;
         int i;
  };
   int main()
  {
    union Un un={0};
    //联合变量的定义
    un.i=0x11223344;
    un.c=0x55;
    printf("%x\n",un.i);
    return 0;
  }

图解见下:

i 和 c 共用一块内存空间,所以联合体也叫共用体,同一时间只能使用 i 和 c 中的一个。

3. 相同成员的结构体和联合体对比

我们再对比一下相同成员的结构体和联合体的内存布局情况。

cs 复制代码
  struct S
 {
    char c;
    int i;
 };

  struct S s={0};
cs 复制代码
  union Un
 {
    char c;
    int i;
 };

 union Un un={0};

4. 联合体大小的计算

  • 联合体的大小至少是最大成员的大小。
  • 当最大成员的大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
cs 复制代码
    #include<stdio.h>
    union Un1
   {
      char c[5];
      int i;
   };
    
    union Un2
   {
     short c[7];
     int i;
   };
 
    int main()
   {
      printf("%zd\n",sizeof(union Un1));
      printf("%zd\n",sizeof(union Un2));
   
      return 0;
   }

计算一个数组的大小,就是这个数组类型大小 * 数组成员个数

【例如】

short [7],2*7=14。

对于 union Un2,我们来计算,首先最大成员的大小是14,最大对齐数为 4,但是14不是最大对齐数的整数倍,那就要对齐到最大对齐数的整数倍,即为16。union Un1同理。

我们发现,对于同样成员的结构体和联合体,联合体有时会占用更少的内存,可以节省空间。

下面我们举个栗子,看看在什么情况下适用联合体。

我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。每种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

图书:书名、作者、页数

杯子:设计

衬衫:设计、可选颜色、可选尺寸

以结构体的的方式写

cs 复制代码
struct gift_list
{
   //公共属性
   int stock_number;//库存量
   double price;    //定价
   int item_type;   //商品类型

   //特殊类型
   char title[20];  //书名
   char author[20]; //作者
   int num_pages;   //页数
  
   char design[30]; //设计
   int colors;      //颜色
   int sizes;       //尺寸
};

这样的结构体设计很简单,用起来也比较方便,但是其中包含了所有的属性,这样就导致结构体的大小就会偏大,浪费内存,并且其中属性并非所有的商品都有。所以我们可以把公共的属性单独写出来,剩余属于各种商品本身的属性使用联合体,这样可以节省内存空间。

cs 复制代码
struct gift_list
{
   //公共属性
   int stock_number;//库存量
   double price;    //定价
   int item_type;   //商品类型

   union 
  {
     struct 
    {   
        char title[20];  //书名
        char author[20]; //作者
        int num_pages;   //页数
    }book;
     struct
    {  
         char design[30]; 设计
    }mug;
     struct
    {
        char design[30]; //设计
        int colors;      //颜色
        int sizes;       //尺寸
    }shirt; 
   }item;
};      

上面结构体和联合体都是匿名,因为这些类型只会被使用一次。

5. 用联合体判断当前机器大小端

写一个程序,判断当期机器是大端,还是小端。

cs 复制代码
int check_sys()
{
    union Un
   {
      char c;
      int i;
   };
   un.i=1;
   return un.c;
}

二、枚举

1. 枚举类型的声明

枚举即列举,把可能取值一一列举出来。

cs 复制代码
enum Day
{
    Mon;
    Tues;
    Wed;
    Thur;
    Fri;
    Sat;
    Sun;
};

上面定义的 enum Day 是枚举类型。{} 里面的内容是枚举类型的可能取值,也叫 枚举常量

这些可能取值都是有值的,默认从0开始,依次递增1,在声明枚举类型的时候也可以赋初值。

cs 复制代码
enum Color
{
    Blue=3
    Red=4;
    Pink=7;
    Black=9;
};

2. 枚举类型的优点

我们可以使用 #define 定义常量,为什么要使用枚举类型?

  1. 增加代码的可读性和可维护性;
  2. 和 #define 定义的标识符比较枚举有类型检查,更加严谨;
  3. 便于调试,预处理阶段会删除 #define 定义的符号;
  4. 使用方便,一次可以定义多个常量;
  5. 枚举常量遵循作用域规则,枚举声明在函数内,只能在函数内使用。

3. 枚举类型的使用

cs 复制代码
enum Color
{
    RED=3;
    GREEN=6;
};

enum Color clr = GREEN;  //使用枚举常量给枚举变量赋值

完------

期待我们下一次相遇------

像极了_永彬Ryan.B_高音质在线试听_像极了歌词|歌曲下载_酷狗音乐酷狗音乐为您提供由永彬Ryan.B演唱的高清音质无损像极了mp3在线听,听像极了,只来酷狗音乐!https://t1.kugou.com/song.html?id=2rsi1cbCPV2

相关推荐
努力的派大星星23 分钟前
【Material-UI】Autocomplete中的禁用选项:Disabled options
开发语言·javascript·ui·material-ui
Pandaconda25 分钟前
【C++ 面试 - 基础题】每日 3 题(一)
开发语言·c++·后端·面试·职场和发展
萨达大26 分钟前
C# 串口通信(通过serialPort控件发送及接收数据)
开发语言·c#
临街的小孩29 分钟前
yolov8 剪枝
算法·yolo·剪枝
╰★忝若冇凊★丶1 小时前
C++面试基础算法的简要介绍
c++·算法·排序算法
Pandaconda2 小时前
【Golang 面试 - 进阶题】每日 3 题(十七)
开发语言·后端·面试·职场和发展·golang
Ordinary~2 小时前
char类型和int类型
java·开发语言
EricWang13582 小时前
[Kimi 笔记]“面向搜索引擎”
开发语言
EricWang13582 小时前
[kimi笔记].net平台
开发语言
近听水无声4772 小时前
排序算法2:直接选择排序与快速排序
数据结构·算法·排序算法