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

先赞后看已成习惯!!!

联合体

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!!!点个赞走吧!!!

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值