C语言之旅:自定义类型(联合和枚举)

news/2024/12/22 14:29:42/

目录

一.联合体

1.1 联合体的声明

1.2 联合体的使用

1.3 为什么输出 4呢?

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

1.5 联合体大小对比

1.6使用联合体判断大小端

二.枚举类型

2.1枚举类型的例举:

 2.2枚举类型的优点

2.3 枚举类型的使用


在上篇文章中已经介绍了结构体。另外,C语言还提供了另外两种数据类型——联合体(union)和枚举(enum),它们各自具有独特的功能和用途。本文将带你深入了解联合体和枚举的概念、用法以及它们在实际编程中的应用。

一.联合体

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

但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。

所以联合体也叫:共⽤体。 给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

1.1 联合体的声明

union Un
{char c;int i;
};

1.2 联合体的使用

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

输出结果:4

1.3 为什么输出 4呢?

 int类型的大小通常是4个字节(byte)。由于联合体的大小至少足够大以容纳其最大的成员,因此Un联合体的大小至少应该是int类型的大小,所以输出为 4。

代码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;
}

输出结果:

012FFD0C
012FFD0C
012FFD0C

这段代码输出了三个地址,它们分别是联合体Un的int成员i的地址、char成员c的地址,以及整个联合体变量un的地址。 

 代码2:

#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;
}

输出结果:

11223355

 

 un.i赋值0x11223344,这是一个十六进制数,它会被存储在un联合体所分配的内存中。因为int类型通常占用4个字节,所以0x11223344会被完整地存储在这4个字节中。

然后,代码又对un.c赋值0x55。由于un.c和un.i共享同一块内存,这个赋值会覆盖un.i的最低有效字节(即char类型所占用的字节)。

那么,0x55会覆盖0x11223344的最低字节,变成0x11223355

最后,代码打印un.i的值,由于我们已经修改了它的最低字节,所以输出的是11223355。(小端机器)。

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

代码示例:

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

1.5 联合体大小对比

• 联合的大小至少是最⼤成员的⼤⼩。

• 当最大成员大小不是最⼤对⻬数的整数倍的时候,就要对齐到最大对齐数的整数倍。

代码示例:

#include <stdio.h>
union Un1
{char c[5];int i;
};
union Un2
{short c[7];int i;
};
int main()
{//下⾯输出的结果是什么? printf("%d\n", sizeof(union Un1));printf("%d\n", sizeof(union Un2));return 0;
}

输出结果:
8
16

由于 char 数组的大小是5个字节,而 int 通常需要4字节对齐,编译器可能会选择增加1个字节的填充(padding),使得整个 union Un1 的大小为8个字节,以满足 int 的对齐要求。 

short c[7] 需要14个字节,这超过了 int 的4个字节,所以 union Un2 的大小将是14个字节。与 union Un1 类似,由于内存对齐的原因,编译器可能会增加额外的填充。在这种情况下,编译器可能会添加2个字节的填充,使 union Un2 的总大小为16个字节。

使用联合体可以节省空间。

1.6使用联合体判断大小端

代码示例:

#include <stdio.h>    int check_sys()    
{    union    {    int i;    char c[sizeof(int)]; // 使用字符数组以便访问int的各个字节    } un;    un.i = 1; // 设置int为1    // 检查int的最低有效字节(在小端系统中应该是1)    return *(char *)&un.i == 1; // 如果返回true(非零),则是小端系统;如果返回false(零),则是大端系统    
}    int main()    
{    if (check_sys()) {    printf("这是一个小端系统。\n");    } else {    printf("这是一个大端系统。\n");    }    return 0;    
}

二.枚举类型

枚举类型(enum)是一种用户定义的数据类型,枚举(enum)顾名思义就是⼀⼀列举。把可能的取值⼀⼀列举。

2.1枚举类型的例举:

例如:

一周的星期⼀到星期日是有限的7天,可以一一列举

 //星期
enum Weekday 
{  Sunday,  Monday,  Tuesday,  Wednesday,  Thursday,  Friday,  Saturday  
};

性别有:男、女、保密,也可以一一列举 

//性别
enum Sex 
{  Male,  Female,  Cfidntl  
};

 2.2枚举类型的优点

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。

3. 便于调试,预处理阶段会删除 #define 定义的符号

4. 使方便便,一次可以定义多个常量

5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

2.3 枚举类型的使用

#include <stdio.h>  enum Color 
{  Red,  Green,  Blue,     
};  int main(){  // 声明一个Color类型的变量  enum Color myColor;  myColor = Red;  switch (myColor) {  case Red:  printf("颜色是红色。\n");  break;  case Green:  printf("颜色是绿色。\n");  break;  case Blue:  printf("颜色是蓝色。\n");  break;  default:  printf("未知的颜色。\n");  break;  }  return 0;  
}

 注意,在C语言中,枚举常量默认从0开始,并且每个后续常量比前一个常量大1。因此,在这个例子中,Red的值为0,Green的值为1,Blue的值为2

当然也以拿整数给枚举变量赋值。在C语⾔中是可以的,但是在C++是不行的,C++的类型检查⽐ 较严格。

代码示例:

enum Color 
{  Red = 1,  Green = 2,  Blue = 3  
};


http://www.ppmy.cn/news/1461857.html

相关文章

PyTorch之list、ndarray、tensor数据类型相互转换

温故而知新&#xff0c;可以为师矣&#xff01; 一、参考资料 python中list、numpy、torch.tensor之间的相互转换 二、常用操作 list 转 numpy ndarray np.array(list) import numpy as npa_list [[j for j in range(5)] for i in range(3)] a_ndarray np.array(a_lis…

智能终端RK3568主板在智慧公交条形屏项目的应用,支持鸿蒙,支持全国产化

基于AIoT-3568A的智慧公交条形屏&#xff0c;可支持公交线路动态展示&#xff0c;语音到站提醒&#xff0c;减少过乘、漏乘的情况&#xff0c;有效提高了公交服务效率和质量&#xff0c;为乘客提供了更舒适、更安全和更方便的出行体验&#xff0c;为城市的发展增添了新的活力。…

QT——tableWidget-跳变之舞V1.0-记录学习【1】

QT——tableWidget-跳变之舞V1.0-记录学习【1】 文章目录 QT——tableWidget-跳变之舞V1.0-记录学习【1】前言一、利用QT创建项目文件1.1 完整项目文件如下图所示:1.2 演示&#xff1a; 二、声明文件&#xff1a;2.1 主界面声明文件:mainwindow.h&#xff1b;2.2 控制窗口声明文…

Python中数据库操作pymysql和 sqlalchemy

在python中操作mysql数据库&#xff0c;主要用到两个库&#xff0c;pymysql和 sqlalchemy。分别进行介绍 安装 安装没啥好说的&#xff0c;其实就是pip install就完事 pip install pymysql pip install sqlalchemypymsql操作数据库 创建连接 以下语句省略了import语句&…

计算机网络-负载均衡算法

计算机网络中的负载均衡算法是决定如何将请求分发到各个服务器的关键。目前负载均衡算法主要分为静态负载均衡算法和动态负载均衡算法&#xff0c;具体包括以下几种&#xff1a; 静态负载均衡算法&#xff1a; 1.轮询法&#xff08;Round Robin&#xff09;&#xff1a;按照顺…

Ardupilot Rpanion iperf网络性能测试

Ardupilot Rpanion iperf网络性能测试 1. 源由2. 分析3. 安装4. 测试4.1 第一次测试4.1.1 iperf测试参数A4.1.1.1 测试链路14.1.1.2 测试链路24.1.1.3 测试链路3 4.1.2 iperf测试参数B - 测试链路34.1.2.1 测试数据4.1.2.2 数据简单分析4.1.2.3 数据深入分析4.1.2.4 模拟测试网…

element-plus 工作经验总结

Element-plus 文章目录 Element-plus忠告: 最好锁定版本, 免得更新更出 BUG 来了el-drawer 设置 modal"false" 后, 遮罩元素仍存在, 点不了空白的地方el-tree 大数据量时接收 check-change 事件报错导致涉及多个节点的操作没执行完毕el-table 表头 show-overflow-too…

Linux---编辑器vim的认识与简单配置

前言 我们在自己的电脑上所用的编译软件&#xff0c;就拿vs2022来说&#xff0c;我们可以在上面写C/C语言、python、甚至java也可以在上面进行编译&#xff0c;这种既可以用来编辑、运行编译&#xff0c;又可以支持很多种语言的编译器是一种集成式开发环境&#xff0c;集众多于…