浅析 C 语言的共用体、枚举和位域

前言

最近在尝试阅读一些系统库的源码,但是其中存在很多让我感到既熟悉又陌生的语法。经过资料查阅,发现是 C 语言中的共用体和位域。于是,趁着课本还没有扔掉,将一些相关的知识点记录在本文。

文章目录

  • 前言
  • 共用体 (union)
  • 枚举 (enum)
  • 位域
  • 参考资料

共用体 (union)

公用体和结构体相似,也是一种数据构造机制。但是结构体中的各成员变量顺序排列存储,每个成员变量都有自己独立存储空间,而共用体中所有成员变量共享同一片内存区域,一个共用体变量在每个时刻里只能保存它的某个成员变量的值

定义格式如下:

union 共用体名 {
	成员列表
};

下面是共用体和结构体占用内存的情况:

#include <stdio.h>

union UnionData {
    int a;
    float b;
    double c;
    char d;
};

struct StructData {
    int a;
    float b;
    double c;
    char d;
};

int main() {
    printf("%lu %lu\n", sizeof(UnionData), sizeof(StructData));
    return 0;
}

控制台输出结果:

8 24

在这里插入图片描述
共用体能支持在同一块内存区域对不同的数据类型进交替使用,增加了灵活性,节省了内存,通常在系统库中会有所应用。

枚举 (enum)

枚举 (enumeration) 是一系列命名的整型常量,它是一种基本数据类型,而不是一种构造类型。在“枚举”类型的定义中,我们需要列举出所有可能值,就像列举一周七天、一年四季等。

定义格式如下:

enum 枚举名 {枚举列表};

枚举的使用例子如下:

#include <stdio.h>

// 枚举定义
enum Season {
    SeasonSpring = 1,
    SeasonSummer,
    SeasonAutumn, 
    SeasonWinter
};

int main () {
    Season a = SeasonSpring;
    switch (a) {
    case SeasonSpring:
        printf("SeasonSpring\n");
		break;
    case SeasonSummer:
        printf("SeasonSummer\n");
		break;
    case SeasonAutumn:
        printf("SeasonAutumn\n");
		break;
    case SeasonWinter:
        printf("SeasonWinter\n");
		break;
    }
    return 0;
}

控制台输出结果:

1 2 3

位域

有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。

出于节省内存的角度考虑,就有了位域这种设计。位域是 C 语音中一种特殊的结构体成员,它允许我们指定它所占的内存位数

定义格式如下:

struct 位域结构名 {
	类型说明符 位域名 : 位域长度;
};

说明:

  • 一个位域必须存储在同 1 个字节中,不能跨两个字节。如果一个字节所剩的空间不足以存储下一个位域时,应该从下一个字节开始存储。
  • 位域长度不能大于 1 个字节长度,也就是说不能超过 8 位。
  • 位域的数据类型只能是 int、unsigned int、char、枚举等类型。
  • 位域可以没有位域名,因为无名的位域是不能使用的,所以只是用作填充或调整位置的作用。例如:
    struct BitStruct {
    	int a : 4;
    	int   : 2;  // 空域,不能使用
    	int b : 4;
    	int c : 4;
    }
    

参考资料

  • https://www.runoob.com/cprogramming/c-bit-fields.html
  • https://book.douban.com/subject/26792521/

本文主要对 C 语言中,共用体、枚举和位域等三块内容做简单介绍,涉及到他们在工程中应用的方面很少,如果后面阅读系统源码的过程遇到了,会再做进一步补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/66642.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

理解 Python 的 for 循环

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 在本篇博客中&#xff0c;我们将讨论 Python 中 for 循环的原理。 我们将从一组基本例子和它的语法开始&#xff0c;还将讨论与 for 循环关联的 else 代码块的用处。 然后我们将介绍迭代对象、迭代器和迭代器协议&…

Android 14重要更新预览

Android 14重要更新预览 国际化 Android 14 在 Android 13 的基础上进一步扩展了按应用设定语言功能&#xff0c;提供了一些额外的功能&#xff1a; 自动生成应用的 localeConfig&#xff1a;从 Android Studio Giraffe Canary 7 和 AGP 8.1.0-alpha07 开始&#xff0c;您可以…

Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis tbms

​ 功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查…

【人工智能前沿弄潮】—— SAM自动生成物体mask

SAM自动生成物体mask 由于SAM可以高效处理提示&#xff0c;可以通过在图像上抽样大量的提示来生成整个图像的mask。这种方法被用来生成数据集SA-1B。 类SamAutomaticMaskGenerator实现了这个功能。它通过在图像上的网格中对单点输入提示进行抽样&#xff0c;从每个提示中SAM可…

【动态规划刷题 6】 删除并获得点数 粉刷房子

740. 删除并获得点数 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。 每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] - 1 和 nums[i] 1 的元素。 开始你拥有 0 个点数。…

【数据库】Redis可以替代Mysql吗

Redis和Mysql的搭配 Redis可以替代Mysql吗什么是RedisRedis适用的场景以及优点Redis的缺点 什么是MysqlMysql的优点Mysql缺点 总结 Redis可以替代Mysql吗 Redis不能代替MySQL&#xff0c; Redis和MySQL只能是一种互补。 什么是Redis Redis是一种非关系型数据库&#xff0c;也…

【iPhone】手机还有容量,拍视频却提示 iPhone 储存空间已满

文章目录 前言解决方案 结语 前言 今天在用 iPhone 录像的时候突然提醒我 iPhone储存空间已满 你没有足够的储存空间来录制视频” 可我明明还有 20G 的容量 我非常疑惑&#xff0c;因为我之前还剩1个G都能录像&#xff0c;现在20G反而不行了&#xff0c;于是重启了手机&#…

Kali中AWD靶机环境搭建

Kali中AWD靶机环境搭建 1、kali安装docker2、克隆项目&#xff08;400多M&#xff0c;下载会有点久&#xff09;3、进入项目4、下载镜像5、改镜像名6、比赛环境搭建6.1 启动靶机6.2 连接裁判机&#xff0c;启动check脚本6.3 关闭环境命令 7、 靶机访问方式7.1 web界面访问7.2 s…

代理模式:静态代理+JDK/CGLIB 动态代理

文章目录 1. 代理模式2. 静态代理3. 动态代理3.1. JDK 动态代理机制3.1.1. 介绍 3.1.2. JDK 动态代理类使用步骤3.1.3. 代码示例3.2. CGLIB 动态代理机制3.2.1. 介绍3.2.2. CGLIB 动态代理类使用步骤3.2.3. 代码示例 3.3. JDK 动态代理和 CGLIB 动态代理对比 4. 静态代理和动态…

HTML|计算机网络相关

1.三次握手 第一次握手&#xff1a;客户端首先向服务端发送请求。 第二次握手&#xff1a;服务端在接收到客户端发送的请求之后&#xff0c;需要告诉客户端已收到请求。 第三次握手&#xff1a;客户端在接收到服务端发送的请求和确认信息之后&#xff0c;同样需要告诉服务端已…

【数模】主成分分析PCA

主成分分析(Principal Component Analysis,PCA)&#xff0c;是一种降维算法&#xff0c;它能将多个指标转换为少数几个主成分&#xff0c;这些主成分是原始变量的线性组合&#xff0c;且彼此之间互不相关&#xff0c;其能反映出原始数据的大部分信息。使用场景&#xff1a;一般…

PAT(Advanced Level) Practice(with python)——1023 Have Fun with Numbers

Code N int(input()) D_N 2*N # print(Yes)if len(str(D_N))>len(str(N)):print(No) else:for s in str(D_N):if s not in str(N) or str(D_N).count(s)!str(N).count(s):print("No")breakelse:print(Yes) print(D_N)

【C语言】预处理详解

本文目录 1 预定义符号 2 #define 2.1 #define 定义标识符 2.2 #define 定义宏 2.3 #define 替换规则 2.4 #和## 2.5 带副作用的宏参数 2.6 宏和函数对比 2.7 命名约定 3 #undef 4 命令行定义 5 条件编译 6 文件包含 6.1 头文件被包含的方式 6.2 嵌套文件包含 1 预定义符号 __…

uniapp根据高度表格合并

没有发现比较友好的能够合并表格单元格插件就自己简单写了一个,暂时格式比较固定 一、效果如下 二、UI视图+逻辑代码 <template><view><uni-card :is-shadow="false" is-full

自然语言处理学习笔记(六)————字典树

目录 1.字典树 &#xff08;1&#xff09;为什么引入字典树 &#xff08;2&#xff09;字典树定义 &#xff08;3&#xff09;字典树的节点实现 &#xff08;4&#xff09;字典树的增删改查 DFA&#xff08;确定有穷自动机&#xff09; &#xff08;5&#xff09;优化 1.…

BigDecimal使用总结

BigDecimal Java在java.math包中提供的API类BigDecimal&#xff0c;用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。 在实际应用中&#xff0c;需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算&a…

Leetcode-每日一题【剑指 Offer 06. 从尾到头打印链表】

题目 输入一个链表的头节点&#xff0c;从尾到头反过来返回每个节点的值&#xff08;用数组返回&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,3,2]输出&#xff1a;[2,3,1] 限制&#xff1a; 0 < 链表长度 < 10000 解题思路 1.题目要求我们从尾到头反过…

Python爬虫在电商数据挖掘中的应用

作为一名长期扎根在爬虫行业的专业的技术员&#xff0c;我今天要和大家分享一些有关Python爬虫在电商数据挖掘中的应用与案例分析。在如今数字化的时代&#xff0c;电商数据蕴含着丰富的信息&#xff0c;通过使用爬虫技术&#xff0c;我们可以轻松获取电商网站上的产品信息、用…

401 · 排序矩阵中的从小到大第k个数

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; 九章算法 - 帮助更多程序员找到好工作&#xff0c;硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧 class Solution { public:/*** param matrix: a matrix of intege…

mysql再docker中运行,直接在实体机上运行mysql命令初始化数据库数据

背景 项目上我们使用docker安装mysql&#xff0c;项目启动的时候需要利用sql语句初始化数据。 直接在实体上是识别不到mysql命令的。 实现方式 实现方式1&#xff1a;在docker容器内部执行sql语句 1. 将sql文件上传到容器内 docker cp /root/1.sql d5:/home/ 说明&#…