【自定义类型详解】完结篇—联合体(共用体)与枚举详解

简介: 【自定义类型详解】完结篇—联合体(共用体)与枚举详解

联合体

1. 联合体的定义

联合体又叫共用体,它是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。给联合体其中⼀个成员赋值,其他成员的值也会跟着变化。

联合体的结构类似于结构体,由关键词union和多个成员变量构成:

union (union  tag)
{
member definition;
member definition;

member definition;
} [more  union variables];

union tag为用户自己编译;member definition为成员变量:可以为 int char等等;

[more  union variables]为你设置的联合体名称

2.联合体类型的声明

我们来看一下这个代码:

#define _CRT_SECURE_NO_WARNINGS
 
#include <stdio.h>
//联合类型的声明
union Un
{
  char c;
  int i;
};
 
int main()
{
  //联合变量的定义
  union Un un = { 0 };
 
  //计算连个变量的⼤⼩
  printf("%d\n", sizeof(un));
  return 0;
}

输出值为: 4

为什么是4呢?

在我们设定的联合体中,存在char(1字节)、int(4字节)类型,在联合体的定义中,联合体的成员会共同占用一块内存空间,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)

(1)联合体

union Un
{
  int n;
  char un;
 
};

(2)联合体嵌套

union Un1
{
  int n;
  char un;
 
}; 
union Un2
{
  int n;
  char un;
  union Un1;
};

(3)匿名联合体

union 
{
  int n;
  char un;
 
}; 

(4)自定义联合体

typedef union un
{
  int n;
  char un;
 
}un1; 

让我们在来看下面两段代码

代码1:

#include <stdio.h>
//联合类型的声明
union Un
{
  char c;
  int i;
};
int main()
{
  //联合变量的定义
  union Un un = { 0 };
  // 下⾯输出的结果是⼀样的吗?
  printf("%p\n", &(un.i));
  printf("%p\n", &(un.c));
  printf("%p\n", &un);
  //我们会发现打印的地址是相同的
  return 0;
}

000000EA08B3FAE4
000000EA08B3FAE4
000000EA08B3FAE4

我们会发现他们都指向同一个地址;

代码2:

#include <stdio.h>
//联合类型的声明
union Un
{
  char c;
  int i;
};
int main()
{
  //联合变量的定义
  union Un un = { 0 };
  un.i = 0x11223344;
  un.c = 0x11;
  //这里是16进制
  printf("%x\n", un.i);
  return 0;
}

这里的操作方法与结构体类似,可以利用(.)和(->)操作符

我们再来看看代码2中的输出:

输出:  11 22 33 11

有什么不同的吗 ?  

我们发现在最后位置的44受un.c的赋值的影响变为了11;

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

struct S                               union un
{                                      {
 char c;                                 char c;             
 int i;                                  int i;
};                                     };
struct S s = {0};                      union Un un = {0};

                                              结构体与联合体在内存中的区别

4.联合体的大小计算

  • 至少是最大成员的大小
  • 当最大成员大小不是最大对齐数的整数倍,就要对齐到最大对齐数的整数倍

使用联合体是可以节省空间的,对于具有公共属性的成员时我们就可以利用联合体节省空间:

例如:当我们购买商品时

公共属性:

//商品名

//价格

//类型

......

私有属性:

//书名

//出版商

//作者

......

5.利用联合体判断大小端

回顾:

#include<stdio.h>
 
int check_sys()
{
  int i = 1;
 
  return (*(char*)&i);
  //先取出i的地址,再将i的(int*)转化为char*,最后在解引用,取出低地址的一个字节;
}
 
 
int main()
{
  int ret = check_sys();
  //返回1,则说明低字节放在低地址
  //返回0,则说明高字节放在低地址
  if (ret = 0) {
    printf("大端存储");
  }
  else {
    printf("小端存储");
  }
  return 0;
}

在前面中我们是利用char*和int*读取的字节大小的不同所判断;在这里我们也可以利用相同的原理使用联合体来判断

int check_sys()
{
  union
  {
    int i;
    char c;
  }un;
  un.i = 1;
  return un.c; //返回1是⼩端,返回0是⼤端
}
int main()
{
  int ret = check_sys();
  if (ret == 1)
  {
    printf("⼩端\n");
  }
  else
  {
    printf("⼤端\n");
  }
  return 0;
}

枚举

1.枚举的声明

枚举意为-->列举

(1) 普通枚举
接下来我们举个例子,比如:我们要定义一个星期 , 使用#define 来为每个整数定义一个别名:

#define MON  1
#define TUE  2
#define WED  3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7

我们会发现这个的代码量就比较多,接下来我们看看使用枚举的方式:

enum DAY
{
     MON=1, //指定从1开始,否则默认从0开始
     TUE,
     WED,
     THU,
     FRI,
     SAT,
     SUN
};

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

(2) 匿名枚举
和匿名结构体与匿名联合体类似,枚举也有匿名类型。

enum
{
    APPLE,
    BANANA,
    ORANGE
};

(3) typedef枚举
我们也可以使用typedef简化枚举。

typedef enum DAY
{
    MON = 1, //指定从1开始,否则默认从0开始
    TUE,
    WED,
    THU,
    FRI,
    SAT,
    SUN
}DAY;

7.2 打印枚举常量

typedef enum DAY
{
    MON, 
    TUE,
    WED,
    THU,
    FRI,
    SAT,
    SUN
}DAY;
int main()
{
    for (int i = MON; i < SUN; i++)
    {
        printf("%d ", i);
    }
    return 0;
}

2.枚举的优点

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

枚举的优点:

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

3.枚举的应用

#include <stdio.h>
 
int main()
{
 
    enum color {
       red = 1, green, blue 
//red = 1 是为了防止输入1时,输出为green
    };
    //枚举了
    enum  color favorite_color;
    //用户输入数字来选择颜色 
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): \n");
    scanf("%d", &favorite_color);
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是red\n");
        break;
    case green:
        printf("你喜欢的颜色是green\n");
        break;
    case blue:
        printf("你喜欢的颜色是blue\n");
        break;
    default:
        printf("你没有选择你喜欢的color\n");
    }
 
    return 0;
}#include <stdio.h>
 
int main()
{
 
    enum color {
       red = 1, green, blue 
//red = 1 是为了防止输入1时,输出为green
    };
    //枚举了
    enum  color favorite_color;
    //用户输入数字来选择颜色 
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): \n");
    scanf("%d", &favorite_color);
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是red\n");
        break;
    case green:
        printf("你喜欢的颜色是green\n");
        break;
    case blue:
        printf("你喜欢的颜色是blue\n");
        break;
    default:
        printf("你没有选择你喜欢的color\n");
    }
 
    return 0;
}

oi!!!点个赞走吧!!!


相关文章
|
6月前
|
存储 C语言
自定义类型:联合体和枚举
联合体类型,联合体的大小计算,联合体的实际应用,练习:判断大小端,枚举类型,枚举类型的声明:枚举类型的优点,枚举类型的实际案例:
|
安全 C++
【自定义类型:结构体,枚举,联合】内存对齐的原理和原因
【自定义类型:结构体,枚举,联合】内存对齐的原理和原因
79 0
|
编译器
自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合(上)
自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合(上)
|
编译器 Linux C语言
【C语言】自定义类型:结构体(内存对齐),枚举,联合
【C语言】自定义类型:结构体(内存对齐),枚举,联合
|
编译器 C语言
C语言自定义类型 — 结构体、位段、枚举、联合
本期主要对通讯录三篇博客文章进行补充 通讯录文章:通讯录系列文章 对结构体进行详细介绍,其次讲解位段、枚举、联合体
94 0
|
6月前
|
存储 编译器 Linux
自定义类型——结构体、联合体、枚举
自定义类型——结构体、联合体、枚举
|
6月前
|
编译器 测试技术 C语言
详解自定义类型:枚举与联合体!
详解自定义类型:枚举与联合体!
|
6月前
|
存储 开发框架 .NET
自定义类型:联合体和枚举类型(联合体与结构体的区别)
自定义类型:联合体和枚举类型(联合体与结构体的区别)
|
存储
自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合(中)
自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合(中)
|
存储 编译器
自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合(下)
自定义类型:结构体2.0(初阶+进阶)+位段+枚举+联合(下)