聯合體和枚舉——嵌入式學習筆記

目錄

前言

一、聯合體(共用體)

1、基本概念

2、初始化和引用

(1)初始化

(2)引用

二、枚舉


前言

????????在C語言的編程世界中,我們早已熟悉了結構體struct這種能將不同數據類型捆綁在一起的“打包”神器。但你是否想過,如果有一塊內存,可以靈活地存放不同類型的數據,但在同一時刻只使用其中一種,該如何實現?又是否曾為那些 magic number(魔法數字)和意義不明的整數常量而頭疼?

????????這就是聯合體(union)和枚舉(enum)大顯身手的地方。它們一個是高效利用內存的“變體”專家,一個是提升代碼可讀性與安全性的“語義化”大師。本篇博客將帶你深入淺出,探索這兩個強大工具的奧秘,讓你的C代碼更加專業、優雅和高效。


一、聯合體(共用體)

1、基本概念

說明:

????????聯合體的外在形式跟結構體非常相似,但它們有一個本質的區別:結構體中的各個成員各自獨立,而聯合體的各個成員卻共用一塊內存,因此聯合體也稱為共用體

圖解:

????????

特點:

????????整個聯合體變量的尺寸,取決于聯合體尺寸最大的成員

????????給聯合體的某個成員賦值,會覆蓋其他成員,使它們失效

????????

????????聯合體各成員之間形成一個 "互斥"的邏輯的,在某一個時刻只有一個成員有效

語法:

????????聯合體標簽:用來區分各個不同的聯合體

????????成員: 是包含在聯合體內部的數據,可以是任意的數據類型

基本結構:

union 聯合體標簽
{成員1;成員2;...        
};

2、初始化和引用

(1)初始化

說明:

????????聯合體的操作跟結構體形式上別無二致,但由于聯合體特殊的存儲特性,不管怎么初始化和賦值,最終有且僅有一個成員是有效的

示例代碼:

????????

#include <stdio.h>union node1
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100double f;       // 99.9、59.9char buf[128];  // 優秀、良好、中等、及格、差
};union node2
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100
};// 主函數
int main(int argc, char const *argv[])
{// (1)、聯合體的初始化// 1、普通初始化union node1 n1 = {'A', 90, 99.9, "優秀"};printf("聯合體成員的值 == %d\n",  n1.ch);printf("n1的大小為    == %lu\n", sizeof(n1));   // - 整個聯合體變量的尺寸,取決于聯合體尺寸最大的成員/*報警告:warning: excess elements in union initializer// 翻譯:警告:聯合體初始化器中的元素過多原因:只有第一個成員有效,其它成員賦值無效,也無需賦值- 給聯合體的某個成員賦值,會覆蓋其他成員,使它們失效- 聯合體各成員之間形成一個 "互斥"的邏輯的,在某一個時刻只有一個成員有效*/// 2、指定成員初始化(只有最后一個賦值有效,其它賦值無效,會被覆蓋)union node2 n2 ={.num = 80,.ch  = 'D'};printf("聯合體的成員的值 == %c\n", n2.ch);printf("聯合體的成員的值 == %d\n", n2.num);printf("n2的大小為      == %lu\n", sizeof(n2));return 0;
}

(2)引用

說明:

????????聯合體一般很少單獨使用,而經常以結構體的成員形式存在,用來表達某種互斥的屬性

示例代碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>union node1
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100double f;       // 99.9、59.9char buf[128];  // 優秀、良好、中等、及格、差
};union node2
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100
};typedef struct student       
{char name[128];     char phone[128];int id;int gender;char class[128];float height;float weight;int age;union node1 score;   // 里面有四種互斥的屬性}stu_t, *stu_p;         // 主函數
int main(int argc, char const *argv[])
{// (1)、聯合體的初始化// 1、普通初始化union node1 n1 = {'A', 90, 99.9, "優秀"};printf("聯合體成員的值 == %d\n",  n1.ch);printf("n1的大小為    == %lu\n", sizeof(n1));   // - 整個聯合體變量的尺寸,取決于聯合體尺寸最大的成員/*報警告:warning: excess elements in union initializer// 翻譯:警告:聯合體初始化器中的元素過多原因:只有第一個成員有效,其它成員賦值無效,也無需賦值- 給聯合體的某個成員賦值,會覆蓋其他成員,使它們失效- 聯合體各成員之間形成一個 "互斥"的邏輯的,在某一個時刻只有一個成員有效*/// 2、指定成員初始化(只有最后一個賦值有效,其它賦值無效,會被覆蓋)union node2 n2 ={.num = 80,.ch  = 'D'};printf("聯合體的成員的值 == %c\n", n2.ch);printf("聯合體的成員的值 == %d\n", n2.num);printf("n2的大小為      == %lu\n", sizeof(n2));// (2)、聯合體的引用// 1、聯合體的直接引用(最后的賦值,會將整個聯合體全部覆蓋)n1.ch   = 'C';n1.num  = 120;n1.f    = 59.9;strcpy(n1.buf , "優秀+");printf("n1.buf == %s\n", n1.buf);// 2、聯合體的間接引用(最后的賦值,會將整個聯合體全部覆蓋)union node1 *p1 = &n1;                          // 指針指向的內存的是棧區union node1 *p2 = malloc(sizeof(union node1));  // 指針指向的內存的是堆區(無初始化)bzero(p2, sizeof(union node1));// 棧區指針strcpy(p1->buf, "良好");p1->ch  = 'E';p1->num = 220;p1->f   = 6.28;printf("p1->f == %f\n", p1->f);// 堆區指針strcpy(p2->buf, "中等");p2->num = 330;p2->f   = 12.56;p2->ch  = 'F';printf("p2->f == %c\n", p2->ch);// (3)、聯合體的實際的引用例子struct student stu1 = {0};stu1.score.num = 100;       /*此處可以選擇一下四種評價標準,但同一時間內只能夠選擇其中一種ch;      // A、B、C、Dnum;     // 60、70、80、90、100f;       // 99.9、59.9;        // 優秀、良好、中等、及格、差*/return 0;
}


二、枚舉

說明:

????????枚舉類型的本質是提供一種范圍受限的類型,比如用0-6表示7種顏色,用0-3表示4種狀態,但枚舉在C語言種并未實現其本來應用的效果,直到C++才擁有原本該有的屬性

????????是使用有意義的單詞,來代替無意義的數字,提高程序的可讀性...

語法:

????????enum是關鍵字

????????spectrum是枚舉常量列表標簽,省略的情況下無法定義枚舉變量

格式:

enum 枚舉常量列表標簽
{常量1,常量2,...
}

例子:

// 枚舉類型
enum color{red, orange, yellow=8, green, blue, cyan, purple};
enum {reset, running, sleep, stop};// 枚舉變量
enum color c = yellow;    // 等價于c = 2

要點:

????????枚舉常量實質上就是整型,首個 枚舉常量默認為0

????????枚舉常量在定義時可以賦值,若不賦值,則取值前面的枚舉常量的值加1

????????C語言種,枚舉等價于整型,支持整型數據的一切操作

示例代碼:

#include <stdio.h>// stm32的枚舉的使用(相比define的好處是可以歸類,并且可以迅速且大規模的鋪開)
typedef enum IRQn
{/******  Cortex-M4 Processor Exceptions Numbers ****************************************************************/NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                                          */MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M4 Memory Management Interrupt                           */BusFault_IRQn               = -11,    /*!< 5 Cortex-M4 Bus Fault Interrupt                                   */UsageFault_IRQn             = -10,    /*!< 6 Cortex-M4 Usage Fault Interrupt                                 */SVCall_IRQn                 = -5,     /*!< 11 Cortex-M4 SV Call Interrupt                                    */DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M4 Debug Monitor Interrupt                              */PendSV_IRQn                 = -2,     /*!< 14 Cortex-M4 Pend SV Interrupt                                    */SysTick_IRQn                = -1,     /*!< 15 Cortex-M4 System Tick Interrupt                                *//******  STM32 specific Interrupt Numbers **********************************************************************/// ...
}IRQn_Type;// 表示顏色
enum color      // 有標簽,所以能定義變量
{red,        // 沒有賦值默認為0(后面的值依次+1)orange,     // 1yellow,     // 2green=8,    // 如果賦值了,那么從此數據開始,后面依次+1(前面數據依然遵循前面的規則)blue,       // 9cyan,       // 10   purple      // 11
};
enum            // 沒有標簽,所以不能定義變量
{reset,      // 重啟running,    // 運行sleep,      // 休眠stop        // 停止,關機
};// 主函數
int main(int argc, char const *argv[])
{// (1)、枚舉類型默認初始化和引用enum color c = 1;c = c + 1;printf("c == %d\n", c); // 枚舉等價于整型,支持整型數據的一切操作1// (2)、在實際開發種使用(是使用有意義的單詞,來代替無意義的數字,提高程序的可讀性...)// 枚舉等價于整型,支持整型數據的一切操作2// 1、顏色選擇enum color c_num = 0;printf("請選擇顏色:\n");printf("0、紅色\n");printf("1、橙色\n");printf("2、黃色\n");scanf("%d", (int*)&c_num);  while(getchar()!='\n');switch (c_num){case red:printf("我是紅紅!\n");break;case orange:printf("我是橙橙!\n");break;case yellow:printf("我是黃黃!\n");break;}// 2、機器狀態選擇同上return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95050.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95050.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95050.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SRE命令行兵器譜之思想篇:像SRE一樣思考——命令行不只是工具,更是你的戰友

SRE命令行兵器譜之思想篇:像SRE一樣思考——命令行不只是工具,更是你的戰友 歡迎來到《SRE命令行兵器譜》系列。在深入研究 grep, lsof, tcpdump 這些強大“兵器”的細節之前,我們必須先回答一個更重要的問題: 一個SRE(網站可靠性工程師)在黑色的終端窗口前,腦子里想的…

STL庫——list(類模擬實現)

? ? ? ? ? づ?ど &#x1f389; 歡迎點贊支持&#x1f389; 個人主頁&#xff1a;勵志不掉頭發的內向程序員&#xff1b; 專欄主頁&#xff1a;C語言&#xff1b; 文章目錄 前言 一、基本框架 二、構造函數 三、析構函數 四、賦值重載 五、增刪查改 5.1、push_front/pus…

在PowerPoint和WPS演示讓蝴蝶一直跳8字舞

如何讓PPT中插入的對象按指定的軌跡運動并且一直“停不下來”&#xff1f;簡單三步&#xff1a;①插入對象、②設置路徑動畫、③設置動畫重復。本文以蝴蝶圖片一直跳8字舞為例進行實際操作講解&#xff0c;PowerPoint和WPS演示都一樣操作&#xff0c;本文以WPS演示進行講解。第…

并發編程——06 JUC并發同步工具類的應用實戰

0 常用并發同步工具類的真實應用場景JDK 提供了比synchronized更加高級的各種同步工具&#xff0c;包括ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等&#xff0c;可以實現更加豐富的多線程操作&#xff1b;1 ReentrantLock&#xff08;可重入的占用鎖&#xff0…

Apple登錄接入記錄

Apple文檔——通過 Apple 登錄 使用入門 - 通過 Apple 登錄 - Apple Developer Apple文檔——設計要求——登錄通過 Apple 登錄 | Apple Developer Documentation 插件github版——apple-signin-unity&#xff08;README 中為接入步驟&#xff09; GitHub - lupidan/apple-…

【小程序-慕尚花坊04】網絡請求并發與loading

網絡請求并發與loading一&#xff0c;網絡請求并發與loading1&#xff0c;并發處理1.1&#xff0c;異步實現方式2.2&#xff0c;Promise.all異步方式封裝2&#xff0c;loading加載2.1&#xff0c;loading的基本使用2.2&#xff0c;loading與并發結合案例2.3&#xff0c;loading…

CentOS 7 升級 OpenSSH 10.0p2 完整教程(含 Telnet 備份)

&#x1f539; CentOS 7 升級 OpenSSH 10.0p2 完整教程&#xff08;含 Telnet 備份&#xff09; 注意&#xff1a;為了避免升級 SSH 時無法遠程登錄&#xff0c;建議先啟用 Telnet 服務 作為備用連接方式。 CentOS 7 默認 OpenSSH 版本是 7.x&#xff0c;升級到 10.0p2 需要 源…

aragfw9.dll aqnky-ef.dll aqua dock.dll apscon~1.dll apropdll.dll app_web_yqnqasrp.dll app_web_

在使用電腦系統時經常會出現丟失找不到某些文件的情況&#xff0c;由于很多常用軟件都是采用 Microsoft Visual Studio 編寫的&#xff0c;所以這類軟件的運行需要依賴微軟Visual C運行庫&#xff0c;比如像 QQ、迅雷、Adobe 軟件等等&#xff0c;如果沒有安裝VC運行庫或者安裝…

rabbitMQ延時隊列實現,怎么保證消息的冪等

一、RabbitMQ 延時隊列實現方式 基于 TTL&#xff08;Time-To-Live&#xff09; 死信隊列&#xff08;Dead Letter Queue&#xff09; 這是最常用的實現方式&#xff0c;核心思路是&#xff1a; (1)消息設置過期時間&#xff08;TTL&#xff09; (2)消息過期后進入綁定的死信隊…

前沿技術觀察:從AI 時代到量子計算的下一站

前沿技術觀察&#xff1a;從AI 時代到量子計算的下一站&#x1f680; 技術的浪潮一波接一波&#xff0c;從 人工智能 到 區塊鏈&#xff0c;再到 邊緣計算、元宇宙、量子計算&#xff0c;這些前沿技術正在深刻影響我們的生活與產業格局。 對于開發者和技術愛好者來說&#xff0…

通過Kubernetes安裝mysql5服務

以下是清晰、結構化的操作流程優化說明&#xff0c;按步驟梳理從部署到配置持久化、暴露服務的完整過程&#xff1a;一、基礎部署&#xff1a;快速驗證 MySQL 可用性創建有狀態工作負載進入 KubeSphere 項目 → 工作負載 → 有狀態副本集 → 創建&#xff0c;選擇 通過鏡像創建…

【mysql】SQL 中 IS 與 = 的區別:一個 NULL 值引發的思考

SQL 中 IS 與 的區別&#xff1a;一個 NULL 值引發的思考為什么查詢結果總是少一條數據&#xff1f;可能是 NULL 在搗鬼在 SQL 查詢中&#xff0c;很多開發者都曾遇到過這樣的困惑&#xff1a;明明看起來正確的查詢語句&#xff0c;返回的結果卻總是與預期不符。這往往是因為沒…

openGauss筆記

1、安裝 直接用docker安裝 2、國產化 符合國產化要求 3、客戶端 3.1 dbeaver 社區版本&#xff08;25.1.4&#xff09;即可&#xff0c;驅動建議用離線版本&#xff0c;在官網下載最新的&#xff0c;然后在驅動管理里面進行添加本地的jar 3.1.1 驅動配置3.1.2 依賴 需要java版本…

SQL語言增刪改查之C與R

本節通關要求1、掌握 SQL 語句對數據庫進行的創建 Create 和讀取 Retireve 操作的指令&#xff1b;2、多練習&#x1f3ae;說明&#xff1a;操作對象是數據表中的數據行&#xff0c;也就是表中的記錄。請明確操作對象&#xff0c;不要誤傷友軍。背景&#xff1a;create table i…

棧溢出問題

brpc 的 bthread 默認協程棧大小是 128KB&#xff08;非 pthread 模式&#xff09;。如果在一個bthread中&#xff0c;它執行的函數內定義了一個局部變量map&#xff0c;有很多個元素&#xff0c;map的大小超過了128KB&#xff0c;協程會自動申請新的棧空間嗎&#xff1f;這里要…

Android之穿山甲廣告接入

文章目錄前言一、效果圖二、實現步驟1.引入庫2.build.gradle依賴3.Application初始化3.開屏廣告4.插屏廣告5.懶人做法總結前言 項目接入廣告已經是常見的現象了&#xff0c;但是還有很多朋友或者初學者沒有接觸過&#xff0c;或者沒有接觸過穿山甲&#xff0c;今天就來看一下&…

Web開發工具一套式部署Maven/Nvm/Mysql/Redis

前言&#xff1a; 對于一個純小白且電腦沒有任何環境的計算機學生&#xff0c;如何快速跑通Java前后端項目呢&#xff1f; 先附上百度網盤 地址&#xff1a; Web開發工具 。 以下鏈接來自不同作者&#xff0c;如有侵犯&#xff0c;請聯系我刪除。 1.Jdk 部署地址&#xff1a…

Deepseek法務提示指令收集

參考網絡資料&#xff0c;收集一些法務提示指令&#xff0c;可用于Agent LLM、以及LLM法律相關開發。 https://zhuanlan.zhihu.com/p/22588251815 1 基礎指令 1) 身份認證模塊 【身份與版本聲明】 您是由DeepSeek研發的法律智能輔助系統V4.2版&#xff0c;內核經司法部《生成…

Tiptrans轉運 | 免費5國轉運地址

Tiptrans 是一家總部位于捷克的國際包裹轉運與虛擬地址服務平臺&#xff0c;主要提供全球虛擬收貨地址&#xff08;英國、德國、香港、美國等&#xff09;&#xff0c;讓用戶在當地網店購物&#xff0c;再由 Tiptrans 轉運到海外。除了物流服務&#xff0c;Tiptrans 也提供虛擬…

STM32手動移植FreeRTOS

&#x1f4e6; 準備工作 獲取FreeRTOS源碼: 訪問 FreeRTOS官網 或其 GitHub倉庫 下載最新版內核源碼。 你也可以使用Git克隆&#xff08;注意要包含子模塊&#xff09;&#xff1a;git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules。 準備STM32基礎…