c語言:自定義類型(枚舉、聯合體)

前言:

c語言中中自定義類型不僅有結構體,還有枚舉、聯合體等類型,上一期我們詳細講解了結構體的初始化,使用,傳參和內存對齊等知識,這一期我們來介紹c語言中的其他自定義類型枚舉和聯合體的知識。

1.位段

? ? 在講枚舉,聯合體之前,我們補充上一期結構體剩下的一點知識——位段。

1.1什么是位段

位段的聲明和結構是類似的,有兩個不同:

1.位段的成員必須是 int、unsigned int 或signed int 。

2.位段的成員名后邊有一個冒號和一個數字。

比如:

struct A
{int _a:2;int _b:5;int _c:10;int _d:30;
};

A就是一個位段類型。

那位段A的大小是多少? ?

printf("%d\n", sizeof(struct A));

這就不得不介紹以上的代碼是什么意思了,_a后面的2表示我們只給_a?變量分配兩個比特位的空間,以此類推,后面的5、10、30都是給各自變量分配了該數量的比特位的空間,這是為什么呢?為什么要給一個變量這么小的空間呢?因為有時我們發現有的變量只固定表示一些很小的數值,如_a變量,我們如果只需要它表示0-3的值,給它分配兩個比特位是完全夠的,所以使用位段是為了節省空間的做法,在某些變量只表示固定范圍的數值時,我們就用位段限制它的空間,盡可能去節省空間,那么我們來看這個結構體的空間大小吧:

四個int類型占8個字節,平均占2個字節,在不超出數值表示范圍的情況下,我們用位段省下了一半的空間。

1.2 位段的內存分配?

? ? 既然位段能節省空間,我們就不得不解釋位段是如何分配內存的:

1. 位段的成員可以是 int unsigned int signed int 或者是 char (屬于整形家族)類型

2. 位段的空間上是按照需要以4個字節( int )或者1個字節( char )的方式來開辟的。

3. 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使用位段。

我們來看一段代碼:

//一個例子
struct S
{char a:3;char b:4;char c:5;char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

我們給a、b、c、d、四個變量分別分配了3,4,5,4個比特位,3+4+5+4=16,它們加起來占16個比特位,是不是意味著S占16÷8=2個字節呢?我們計算一下S所占的空間:

出乎我們意料,它占了三個字節,這是因為位段的存儲規則是不確定的。

如果這個結構體占三個字節,那么它內部是這樣存儲的:

因為a占3個比特位,b占四個比特位,加起來不超過一個字節,所以它們被放在同一個字節內,而c占5個比特位,字節1空間不夠,所以被放在了字節2,此時字節2還剩3個比特位,d占四個比特位,顯然字節2放不下,又開辟了字節3把d放在里面,剩下一個字節的空間就是這樣丟失的。

?1.3 位段的跨平臺問題

1. int 位段被當成有符號數還是無符號數是不確定的。

2. 位段中最大位的數目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機 器會出問題。

3. 位段中的成員在內存中從左向右分配,還是從右向左分配標準尚未定義。

4. 當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是 舍棄剩余的位還是利用,這是不確定的。

總結

跟結構相比,位段可以達到同樣的效果,并且可以很好的節省空間,但是有跨平臺的問題存在。

2.枚舉

? 枚舉也是c語言中自定義類型的一種,那么枚舉是什么呢?

枚舉顧名思義就是一一列舉。

把可能的取值一一列舉。

比如我們現實生活中:

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

性別有:男、女、保密,也可以一一列舉。

月份有12個月,也可以一一列舉。

這里就可以使用枚舉了。

2.1枚舉類型的定義

相比于結構體的關鍵字為struct,枚舉也有自己的關鍵字:enum,了解了它的關鍵字,我們來看枚舉的應用實例:如我們要表示一周七天,我們要表示性別,三原色

enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum Sex//性別
{MALE,FEMALE,SECRET
};
enum Color//顏色
{RED,GREEN,BLUE
};

以上定義的 enum Day , enum Sex , enum Color 都是枚舉類型。

{}中的內容是枚舉類型的可能取值,也叫枚舉常量

這些可能取值都是有值的,默認從0開始,依次遞增1,什么意思呢?如我們的Color類型里面的從頭開始為RED,那么它的值就是0,相應的,GREED的值為1,BLUE的值為2,當然在聲明枚舉類型的時候也可以賦初值。

enum Color//顏色
{RED=1,GREEN=2,BLUE=4
};

2.2枚舉類型的優點?

為什么要使用枚舉?

我們可以使用 #define 定義常量,為什么非要使用枚舉?

枚舉的優點:

1. 增加代碼的可讀性和可維護性

2. 和#define定義的標識符比較枚舉有類型檢查,更加嚴謹。

3. 便于調試

4. 使用方便,一次可以定義多個常量

3.聯合體(共用體)

3.1聯合類型的定義

聯合也是一種特殊的自定義類型 這種類型定義的變量也包含一系列的成員,特征是這些成員公用同一塊空間(所以聯合也叫共用體),關鍵字為union。

比如:

//聯合類型的聲明
union Un
{char c;int i;
};
//聯合變量的定義
union Un un;
//計算連個變量的大小
printf("%d\n", sizeof(un));

3.2聯合體的特點?

?聯合的成員是共用同一塊內存空間的,這樣一個聯合變量的大小,至少是最大成員的大小(因為聯 合至少得有能力保存最大的那個成員)。

問:

union Un
{int i;char c;
};
union Un un;
// 下面輸出的結果是一樣的嗎?
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));

首先我們來分析一下,因為我們聯合體的特點是變量之間共用一塊空間,所以i的地址和c的地址是同一塊,那么它們&i和&c的結果是一樣的:

很顯然,我們的分析是正確的。

3.3聯合大小的計算

聯合體占多少空間,有兩個規則:

1.聯合的大小至少是最大成員的大小。

2.當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。

比如:

union Un1
{char c[5];int i;
};
union Un2
{short c[7];int i;
};
//下面輸出的結果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));

從Un1開始,它的內部定義了一個5個元素的char類型的數組,長度為5個字節,那是否說明它的內存就是5個字節呢?我們回到上面內存規則的第二條—— 當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍,很顯然5不是4的整數倍,所以我們擴展到了8,那么8就是它所占的字節數:

結果完全正確,那么Un2呢,short類型占2個字節,我們定義了一個7個變量的short類型的數組,占14個字節,又創建了一個int類型的變量,考慮到聯合體內存共用的特性,結果肯定不為14+4,我們要考的還是第二條對齊的規則,14不是4的整數倍,由14擴展到了16:

怎么樣,是不是對聯合體內存的規則有一定的了解了呢。

3.4聯合體的實際應用?

? ? 聯合體有很多作用,我們之前講過大小端字節序的概念,還講了設計一個程序判斷當前環境是大端還是小端,學了聯合體之后,我們使用聯合體也能設計這樣的程序且簡單,清晰明了:

union Un
{char c;int i;
};
int main()
{union Un un = { 0 };un.i = 1;if (un.c == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}

我們當前是小端字節序,來看結果吧:

?

是不是很神奇呢。

到這里我們自定義類型的的內容就到此結束了,各位友友讀到這里留下寶貴的三連和評論吧,有不足之處望各位佬佬私信和我交流!!!?

?

?

?

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

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

相關文章

java -jar命令常見使用方法

1、基本用法: java -jar filename.jar這是最簡單的用法,直接指定要運行的 JAR 文件的名稱(包括 .jar 擴展名)。Java 虛擬機(JVM)將加載并執行 JAR 文件中的主類(在 JAR 文件的 META-INF/MANIFE…

微服務:Rabbitmq利用jackson序列化消息為Json發送并接收

消息序列化 Spring默認會把你發送的消息通過JDK序列化為字節發送給MQ&#xff0c;接收消息的時候&#xff0c;再把字節反序列化為Java對象。 我們可以配置JSON方式來序列化&#xff0c;這樣體積更小&#xff0c;可讀性更高。 引入依賴&#xff1a; <dependency><g…

燈珠對LED顯示屏性能的影響

LED顯示屏作為現代顯示技術的重要組成部分&#xff0c;廣泛應用于廣告、信息發布、交通指示等領域。燈珠作為LED顯示屏的核心組件&#xff0c;對其性能有著決定性的影響。本文將從八個關鍵方面探討燈珠對LED顯示屏性能的影響。 1. 視角 LED顯示屏的視角由燈珠的視角決定。戶外顯…

原型鏈、閉包、手寫一個閉包函數、 閉包有哪些優缺點、原型鏈繼承

什么是原型鏈&#xff1f; 原型鏈是一種查找規則 為對象成員查找機制提供一個方向 因為構造函數的 prototype 和其實例的 __ proto __ 都是指向原型對象的 所以可以通過__proto__ 查找當前的原型對象有沒有該屬性, 沒有就找原型的原型, 依次類推一直找到Object( null ) 為…

【YOLOv9改進[Conv]】使用YOLOv10的空間通道解耦下采樣SCDown模塊替換部分CONv的實踐 + 含全部代碼和詳細修改內容

本文將使用YOLOv10的空間通道解耦下采樣SCDown模塊替換部分CONv的實踐 ,文中含全部代碼和詳細修改內容。 目錄 一 YOLOv10 1 空間通道解耦下采樣 2 可視化

UFS協議—新手快速入門(二)【5-6】

目錄 五、UFS協議棧 六、UFS技術演進與詳解 1、UFS應用層 設備管理器 任務管理器 2、UFS傳輸層 3、UFS互聯層 UFS協議—新手快速入門&#xff08;一&#xff09;【1-4】 五、UFS協議棧 UFS&#xff08;Universal Flash Storage&#xff09;協議是針對固態存儲設備&…

渡眾機器人自動駕駛小車運行Autoware 實現港口物流運輸

Autoware 是一個開源的自動駕駛軟件堆棧&#xff0c;提供了豐富的功能和模塊&#xff0c;用于實現自動駕駛車輛的感知、定位、規劃和控制等功能。北京渡眾機器人公司將多款自動駕駛小車在多場景運行Autoware &#xff0c;它可以實現以下功能&#xff1a; 1. 感知&#xff1a;利…

Spark的性能調優——RDD

前言 RDD 是 Spark 對于分布式數據集的抽象&#xff0c;每一個 RDD 都代表著一種分布式數據形態。比如 lineRDD&#xff0c;它表示數據在集群中以行&#xff08;Line&#xff09;的形式存在&#xff1b;而 wordRDD 則意味著數據的形態是單詞&#xff0c;分布在計算集群中。 參…

職稱繼續教育--專業課2

單選題&#xff08;共10題&#xff0c;每題3分&#xff09; 1、根據本講&#xff0c;“水十條”總體框架包括&#xff08;&#xff09;個層次。 C、5 2、根據“水十條”目標指標層&#xff0c;到2020年&#xff0c;地級及以上城市建成區的黑臭水體控制&#xff08;&#xff09…

數據挖掘綜合案例-家用熱水器用戶行為分析與事件識別

文章目錄 1. 背景與挖掘目標2. 分析方法與過程3. 數據分析3.1 數據探索分析3. 2 數據預處理1. 屬性約束2. 劃分用水事件3. 確定單次用水事件時長閾值4. 屬性構造5.篩選候選洗浴事件 3.3 模型構建3.4 模型檢驗 4. 思考總結 1. 背景與挖掘目標 隨著國內大家電品牌的進入和國外品…

了解CAN功能

了解CAN功能&#xff0c;學習CAN功能&#xff0c;理解CAN和串口的區別&#xff0c;以及它和RS485的相似之處。 1、“多主機”特性 在CAN網絡通訊中&#xff0c;無需其它設備同意&#xff0c;每個CAN設備都可以主動向外發送數據&#xff0c;且所有設備都會收到數據&#xff0c…

【面試干貨】 非關系型數據庫(NoSQL)與 關系型數據庫(RDBMS)的比較

【面試干貨】 非關系型數據庫&#xff08;NoSQL&#xff09;與 關系型數據庫&#xff08;RDBMS&#xff09;的比較 一、引言二、非關系型數據庫&#xff08;NoSQL&#xff09;2.1 優勢 三、關系型數據庫&#xff08;RDBMS&#xff09;3.1 優勢 四、結論 &#x1f496;The Begin…

孵化器補貼政策提問模板

對于一些需要創業的人來說&#xff0c;找場地是非常非常難的&#xff0c;一個好的場地能夠提高創業的成功率&#xff0c;下面這些內容對于孵化器產業園的政策有一個好的提問&#xff0c;可以幫助你們了解這個孵化器合不合適。需要創業的人可以收藏 某孵化器政策示例 提問模板 …

源代碼先轉字節碼,再轉機器碼的過程

編程語言分類 1. 機器語言 直接使用 (101010) 二進制指令去編寫程序, 等于 直接操作硬件優點 : 最底層, 離計算機最近, 執行速度快缺點 : 復雜難記, 開發效率最低, 2. 匯編語言 用英文標簽代替一組二進制指令, 本質上仍然是 直接操作硬件優點 : 比較底層, 執行速度最快缺點 …

【競技寶】歐洲杯:德國被烏克蘭逼平,27腳射門仍難得分!

歐洲杯前的熱身賽已經全面開啟,東道主德國隊算是打響了熱身賽的第一槍,只可惜他們在主場0比0被烏克蘭逼平。整場比賽,德國隊都占據明顯優勢,全場比賽轟出27腳射門,可是卻無法實現破門。這個時候德國球迷似乎回想到了前兩屆世界大賽,球隊被“鋒無力”支配的恐懼。 本場比賽德國隊…

如何制作Peppol文件?

Peppol (Pan-European Public Procurement Online) 是一種用于跨境電子采購的標準協議和網絡。它允許企業和政府機構以電子方式交換文件&#xff0c;如電子發票、訂單和發貨單。如果你需要制作Peppol文件&#xff0c;可以參考如下步驟&#xff1a; 準備必要工具和資源 1.Pepp…

Serif Affinity 2.5 (macOS, Windows) - 專業創意軟件

Serif Affinity 2.5 (macOS, Windows) - 專業創意軟件 Affinity Designer 2, Affinity Photo 2, Affinity Publisher 2 請訪問原文鏈接&#xff1a;Serif Affinity 2.5 (macOS, Windows) - 專業創意軟件&#xff0c;查看最新版。原創作品&#xff0c;轉載請保留出處。 作者主…

C語言什么打開?件后要及時關閉?

一、問題 對?件讀寫之前&#xff0c;需要使? fopen( ) 函數打開該?件&#xff1a;在使?完?件后&#xff0c;需要及時關閉?件。那么&#xff0c;為什么要及時關閉?件呢&#xff1f; 二、解答 ?件打開的過程是將存放在磁盤等外部設備上的?件讀?到內存中&#xff0c;以…

【第二節】C/C++數據結構之線性表

目錄 一、線性表基本說明 1.1 基本概念 1.2 抽象數據類型 1.3 存儲結構 1.4 插入與刪除的區別 1.5 順序存儲和鏈式存儲的優缺點 二、鏈表 2.1 基本概念 2.2 抽象數據類型 2.3 單鏈表的定義 2.4 單鏈表的基本操作 2.5 單鏈表模板形式的類定義與實現 三、單向循環鏈…

項目迭代中新老邏輯切換入口

前言 ? 日常我們在項目開發中經常會進行項目迭代&#xff0c;比如說開發初期設定的代碼邏輯根據功能需求迭代逐漸發現越來越難用&#xff0c;或者改動是對整體較大時&#xff0c;往往會進行專項處理&#xff0c;對這個邏輯進行改造。 ? 那么就會涉及到原先被調用方切換接口…