C语言之联合和枚举

news/2024/5/18 5:21:52 标签: c语言, 开发语言, 联合体, 枚举, 字节序

C语言之联合和枚举

文章目录

1. 联合体

1.1 联合体的声明

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体
联合体其中⼀个成员赋值,其他成员的值也跟着变化

1.2 联合体的特点

代码一:

#include <stdio.h>

union U
{
	char a;
	int b;
};
int main()
{
	union U uu = { 0 };
	printf("%zd\n", sizeof(uu));
	return 0;
}

代码运行结果:>
4

结论:联合的成员是公用一块空间的,联合体变量的大小至少是最大成员的大小(至少确保能存下最大的那个成员)

代码二:

#include <stdio.h>

union U
{
	char a;
	int b;
};
int main()
{
	union U uu = { 0 };
	printf("%p\n", &(uu.a));
	printf("%p\n", &(uu.b));
	printf("%p\n", &uu);
	return 0;
}

代码运行结果:>
012FFD90
012FFD90
012FFD90

可以看到无论是联合体的地址还是联合体成员的地址都是一样的,说明他们共用同一块空间

代码三:

#include <stdio.h>

union U
{
	char a;
	int b;
};
int main()
{
	union U uu = { 0 };
	uu.b = 0x11223344;
	uu.a = 0x55;
	printf("%#x\n", uu.b);
	return 0;
}

%#x打印的是带0x的十六进制数,0x11223344是一个十六进制数

代码运行结果:>
0x11223355

在这里插入图片描述
由于是小端字节序存储,优先存低字节的也就是44,然后通过char修改了第一个字节的内容,将44修改成了55,所以打印结果为0x11223355

1.3 结构体和联合体对比

union U
{
	char a;
	int b;
};
struct S
{
	char a;
	int b;
};

在这里插入图片描述
相对于结构体,联合体较节省空间

1.4 联合体大小的计算

  1. 联合体大小至少是联合体中最大成员的大小
  2. • 当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍,和结构体一样,联合体也是有对齐的
#include <stdio.h>

union U1
{
	char a[7];
	int b;
};
union U2
{
	short a[7];
	int b;
};
int main()
{
	union U1 u = { 0 };
	union U2 uu = { 0 };
	printf("%zd\n", sizeof(u));
	printf("%zd\n", sizeof(uu));
	return 0;
}

代码运行结果如下:>
8
16

联合体U1中有两个成员,char a[7] int b 其中最大成员为char a[7],为7个字节,char为1字节,默认对齐数为8,取较小值1,int为4字节,默认对齐数为8,取较小值4,所以两个成员中的最大对齐数为4,最大成员的大小为7,不是最大对齐数4的倍数,所以将对齐至8字节,对齐之后才是联合体的大小

同理联合体U2,也有两个成员,最大成员的大小为14字节,不是最大对齐数4的倍数,所以将对齐至16字节,对齐之后才是联合体的大小

1.5 联合体小练习

要求:写一个代码,判断当前机器的字节序

代码一:

#include <stdio.h>

int check_sys()
{
	int n = 1;
	return *(char*)&n;
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

小端字节序,将低字节内容存到低地址,高字节内容存到高地址
大端字节序,将高字节内容存到低地址,低字节内容存到高地址
内存使用优先使用低地址

1的十六进制为00 00 00 01
小端字节序为 01 00 00 00
大端字节序为 00 00 00 01

取出1的地址,将其从int*类型的指针强制类型转化为char*类型的地址,这样解引用的时候就会访问低地址处的内容,如果解引用得到1则是小端,得到0则为大端

代码二:
使用联合体的方式

#include <stdio.h>

int check_sys()
{
	union
	{
		char a;
		int b;
	}un;
	un.b = 1;
	return un.a;
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

通过联合体公用同一块空间的方式,如果第一个字节中存的是1则是小端,如果存的是0则是大端

2. 枚举

2.1 枚举类型的声明

枚举顾名思义就是一一列举

enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

枚举类型:enum Day
枚举常量:Mon,Thus,… //枚举常量使用逗号隔开,最后一个常量不需要

枚举常量是有值的,第一个常量的值默认从0开始,依次递增1,也可以在声明的时候为枚举常量赋值

enum Color
{
	RED = 4,
	YELLOW = 8,
	BLUE = 12
};

2.2 枚举类型的优点

#define关键字为什么还要使用枚举

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

2.3 枚举类型的使用

#include <stdio.h>

enum Color
{
	RED = 4,
	YELLOW = 8,
	BLUE = 12
};

int main()
{
	enum Color clr = BLUE;//使用枚举常量为变量赋值
	return 0;
}
#include <stdio.h>

enum Color
{
	RED = 4,
	YELLOW = 8,
	BLUE = 12
};

int main()
{
	enum Color clr = 12;//使用整数为变量赋值,12 == BLUE
	return 0;
}

在C语言中,对其规定不是很严格,在C++中,C++的类型检查比较严格,这是个语法错误,无法使用整型对枚举变量赋值


http://www.niftyadmin.cn/n/5243194.html

相关文章

unity 2d 入门 飞翔小鸟 飞翔脚本(五)

新建c#脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Fly : MonoBehaviour {//获取小鸟&#xff08;刚体&#xff09;private Rigidbody2D bird;//速度public float speed;// Start is called before the first frame up…

【从0配置JAVA项目相关环境2】node.js + 前端 从配置到运行

运行前端项目 写在最前面一、安装node.js二、运行前端项目1. 运行 npm install2. 运行 npm run serve报错Error: error:0308010C:digital envelope routines::unsupported方法1&#xff1a;设置 NODE_OPTIONS &#xff08;没用&#xff09;方法2&#xff1a;更改Node.js版本方法…

Xcode15 Library ‘iconv.2.4.0‘ not found

Xcode 15运行老代码报错&#xff1a;Library iconv.2.4.0 not found 解决&#xff1a; TARGETS-->Bulid Phases --> Link Binary With Libraries 添加一个“Libiconv.tbd”, 同时把原来的 “libiconv.2.4.0.tbd”删除&#xff08;一定要删除&#xff0c;不然运行还是…

ElasticSearch 谈谈分词与倒排索引的原理

ElasticSearch是一个基于Lucene的搜索服务器。Lucene是Java的一个全文检索工具包&#xff0c;而ElasticSearch则是一个分布式搜索和分析引擎。下面&#xff0c;我们将详细讨论ElasticSearch中的分词和倒排索引的原理。 分词&#xff1a; 在ElasticSearch中&#xff0c;分词是…

Docker架构、镜像操作和容器操作

一、docker基本管理和概念 1、概念 docker&#xff1a;开源的应用容器引擎。基于go语言开发的。运行在Linux系统中的开源的轻量级的“虚拟机” docker的容器技术可用在一台主机上轻松到达为任何应用创建一个轻量级到的&#xff0c;可移植的&#xff0c;自给自足的容器 dock…

城市之眼:数据可视化在智慧城市的角色

作为智慧城市建设的核心组成部分&#xff0c;数据可视化扮演着至关重要的角色。在城市中&#xff0c;数据源源不断地产生&#xff0c;涵盖了从交通流量、环境质量到市民需求等各个方面。而数据可视化作为将这些数据呈现出来的手段&#xff0c;对智慧城市的发展起着关键性的作用…

Linux(ubuntu)利用ffmpeg+qt设计rtsp_rtmp流媒体播放器(完全从0开始搭建环境进行开发)

一、前言 从0开始搭建Linux下Qt、ffmpeg开发环境。 从安装虚拟机开始、安装Linux(Ubuntu)系统、安装Qt开发环境、编译ffmpeg源码、配置ffmpeg环境、编写ffmpeg项目代码、完成项目开发。 完全从0开始搭建环境进行开发 完全从0开始搭建环境进行开发 完全从0开始搭建环境进行开…

电源小白入门学习1——电源系统架构和相关指标

电源小白入门学习1——电源系统架构和相关指标 电源系统架构电源系统的指标及测量方法电源的效率电源的静态电流输出电压调整率纹波测量的注意事项动态负载测试 在开始本期内容之气&#xff0c;我先简单介绍一下我们电源小白学习系列内容&#xff1a;首先我是一个嵌入式小白&am…