第十八講:聯合和枚舉

第十八講:聯合和枚舉

  • 1.聯合體(共用體)
    • 1.1聯合體的聲明
    • 1.2聯合體大小的計算
    • 1.3聯合體的特點
    • 1.4聯合體的使用
      • 1.4.1聯合體的直接使用
      • 1.4.2聯合體直接使用的優化方法
      • 1.4.3聯合體成員中含有數組的使用
      • 1.4.4使用聯合體判斷當前機器是大端排序,還是小端排序
    • 1.5聯合體的具體使用例子
  • 2.枚舉類型
    • 2.1枚舉類型的聲明
    • 2.2枚舉成員值的討論
      • 2.2.1原順序
      • 2.2.2自己進行賦值
    • 2.3枚舉的優點
    • 2.4枚舉類型的使用
      • 2.4.1使用1
      • 2.4.2使用2

1.聯合體(共用體)

1.1聯合體的聲明

聯合體和結構體相似,聯合體也是由一個或多個成員構成,這些成員可以是不同的類型,但是與結構體不同的是,聯合體只為最大的成員分配足夠的內存空間,而聯合體的成員公用同一塊內存空間,所以聯合體也叫共用體,聯合體的聲明如下:

//1.1聯合體的聲明
//聯合體的聲明與結構體類似
union Book
{char name[10];int id;
};int main()
{//聯合體變量的定義union Book b1 = { 0 };return 0;
}

1.2聯合體大小的計算

對于下面的一串代碼,聯合體變量b1的大小是多少,為什么:

union Book
{char name;int id;
};int main()
{//聯合體變量的定義union Book b1 = { 0 };//聯合體變量的大小printf("%zd\n", sizeof(b1));return 0;
}

b1的大小為4,這就是因為:

1.聯合體的大小至少是最大成員的大小
2.當最大成員的大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍

例如:

//計算聯合體的大小
union Un1
{char c[5];//對齊數:1//占五個字節int i;//對齊數:4//占4個字節//所以最大為5個字節,不是4的整數倍,補齊,解果為8
};
union Un2
{short c[7];//14個字節int i;//4個字節//一共為14個字節,不是4的倍數,補齊為16
};
int main()
{printf("%zd\n", sizeof(union Un1));//8printf("%zd\n", sizeof(union Un2));//16return 0;
}

1.3聯合體的特點

既然聯合體的成員共用同一塊內存空間,那我們不妨來分析一下:

//聯合類型的聲明
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;
}

它們的結果為:
在這里插入圖片描述
它們的地址是相同的,所以它們指向同一塊內存空間的地址,那既然指向同一塊空間的地址,對于其中的一個成員進行賦值,其他成員會受到影響嗎:

//聯合類型的聲明
union Un
{char c;int i;
};
int main()
{//聯合變量的定義union Un un = { 0 };un.i = 0x11223344;//先給i賦值,內存中存儲的是:44332211(小端排序)un.c = 0x55;//給c賦值,此時內存中存儲的是:55332211,顯然會影響i的值1printf("%x\n", un.i);//i在內存中的存儲被改變為:55332211,所以輸出的結果為11223355return 0;
}

我們可以畫圖來理解:
在這里插入圖片描述

1.4聯合體的使用

1.4.1聯合體的直接使用

//1.4.1聯合體的直接使用
union Score
{int score1;int score2;
};int main()
{//因為score1和score2占用同一塊內存空間,所以在使用時盡量一個一個進行使用:union Score s1;s1.score1 = 20;//使用score1...(例如:進行打印)printf("%d\n", s1.score1);//使用完s1之后,在使用s2:s1.score2 = 30;//使用score2...(例如:進行打印)printf("%d\n", s1.score2);//這樣才能正確使用score1和score2,否則在使用score1時對score2進行操作很可能改變score1的值return 0;
}

1.4.2聯合體直接使用的優化方法

上面的代碼中,如果想要在一定時間內多次使用多種成員時,無法實現,所以我們探討解決方法:

//1.4.2聯合體直接使用的優化方法
union Score
{int score1;int score2;
};int main()
{union Score s1;s1.score1 = 20;//可以先創建一個保存score1值的變量int pscore1 = s1.score1;//這時我們就可以使用score2了:s1.score2 = 30;//再創建一個保存score2值的變量int pscore2 = s1.score2;//這時想要使用score1,就要將pscore1的值再傳給score1:s1.score1 = pscore1;//使用score1...(例如:進行打印)printf("%d\n", s1.score1);return 0;
}

1.4.3聯合體成員中含有數組的使用

當聯合體成員中包含數組時,情況就有所不同:
在這里插入圖片描述

如果我們這樣進行賦值的話,可以看到它報錯了,正確的使用方法如下:

  1. 使用strcpy函數
union Book
{char name[20];int price;
};int main()
{union Book b1;//先確定書的價錢b1.price = 20;//再確定書的名字//先對結構體進行清空memset(&b1, 0, sizeof(b1));//再使用strcpy函數進行賦值strcpy(b1.name, "tangjiasnashao");return 0;
}
  1. 使用循環
union Book
{char name[20];int price;
};int main()
{union Book b1;//先確定書的價錢b1.price = 20;//再確定書的名字memset(&b1, 0, 20);const char arr[20] = "tangjiasnashao";for (int i = 0; i < strlen(arr); i++)b1.name[i] = arr[i];return 0;
}
  1. 使用標準I/O函數
union Book
{char name[20];int price;
};int main()
{union Book b1;//先確定書的價錢b1.price = 20;//再確定書的名字memset(&b1, 0, 20);scanf("%s", b1.name);return 0;
}

使用fegts函數時換行符也會被存儲,需要額外處理:

union Book
{char name[20];int price;
};int main()
{union Book b1;//先確定書的價錢b1.price = 20;//再確定書的名字memset(&b1, 0, 20);fgets(b1.name, 10, stdin);return 0;
}

1.4.4使用聯合體判斷當前機器是大端排序,還是小端排序

//1.4.4使用聯合體判斷當前機器是大端排序,還是小端排序
union Test
{char a;int b;
};int main()
{union Test t1;t1.b = 1;if (t1.a == 0)printf("大端排序\n");if(t1.a == 1)printf("小端排序\n");return 0;
}

1.5聯合體的具體使用例子

看到聯合體的使用如此繁瑣,我們是不是感覺:還沒有結構體好用,那么就讓我們看一下聯合體的具體使用:

?如,我們要搞?個活動,要上線?個禮品兌換單,禮品兌換單中有三種商品:圖書、杯?、襯衫。
每?種商品都有:庫存量、價格、商品類型和商品類型相關的其他信息:
在這里插入圖片描述
我們對它們進行分析:

struct gift_list
{//公共屬性int stock_number;//庫存量double price; //定價int item_type;//商品類型//特殊屬性,也就是單獨屬性char title[20];//書名char author[20];//作者int num_pages;//?數char design[30];//設計int colors;//顏?int sizes;//尺?
};

如果我們直接創建結構體的話,會占用很多內存,所以我們可以這樣使用:

struct gift_list
{int stock_number;//庫存量double price; //定價int item_type;//商品類型union {struct{char title[20];//書名char author[20];//作者int num_pages;//?數}book;struct{char design[30];//設計}mug;struct{char design[30];//設計int colors;//顏?int sizes;//尺?}shirt;}item;
};

2.枚舉類型

2.1枚舉類型的聲明

枚舉其實就是??列舉

比如:

1.?周的星期?到星期?是有限的7天,可以??列舉
2.性別有:男、?、保密,也可以??列舉
3.?份有12個?,也可以??列舉
4.三原?,也是可以??列舉

這些數據的表示就可以使用枚舉:

//枚舉的聲明
enum Day //星期
{Mon, //每個成員后邊需要加逗號Tues,Wed,Thur,Fri,Sat,Sun //最后一個成員后邊不用加逗號
};enum Sex//性別
{MALE,FEMALE,SECRET
};enum Color//顏?
{RED,GREEN,BLUE
};

2.2枚舉成員值的討論

對于枚舉成員,它們其實是有值的,我們現在對它們的值進行討論:

2.2.1原順序

//2.2.1原順序
enum Day //星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{printf("%d\n", Mon); //0printf("%d\n", Tues); //1printf("%d\n", Wed); //2printf("%d\n", Thur);//3printf("%d\n", Fri); //4printf("%d\n", Sat); //5printf("%d\n", Sun); //6return 0;
}

可見它們的值是從0開始,往后加的

如果我們想要自己給枚舉成員賦值,也是可行的,但是只能在創建枚舉類型時進行賦值,不能在main函數或其他函數中進行更改

2.2.2自己進行賦值

//2.2.2情況1
enum Day //星期
{Mon,Tues,Wed = 7,Thur,Fri,Sat,Sun
};int main()
{printf("%d\n", Mon); //0printf("%d\n", Tues); //1printf("%d\n", Wed); //7printf("%d\n", Thur);//8printf("%d\n", Fri); //9printf("%d\n", Sat); //10printf("%d\n", Sun); //11return 0;
}

2.3枚舉的優點

當然我們可以使用define定義常量,那為什么要使用枚舉呢

枚舉的優點:

  1. 增加代碼的可讀性和可維護性
  2. 和#define定義的標識符比較,枚舉有類型檢查,更加嚴謹。
  3. 便于調試,預處理階段會刪除 #define 定義的符號
  4. 使??便,?次可以定義多個常量
  5. 枚舉常量是遵循作?域規則的,枚舉聲明在函數內,只能在函數內使?

2.4枚舉類型的使用

2.4.1使用1

enum Color//顏?
{RED=1,GREEN=2,BLUE=4
};int main()
{enum Color clr = GREEN;//使?枚舉常量給枚舉變量賦值//后續可以通過這個值進行判斷,比如:if (clr == 	GREEN)printf("YES");return 0;
}

2.4.2使用2

比如當我們想要寫一個簡單的計算器時,會這樣寫:

int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf(" 0:exit \n");printf("*************************\n");printf("請選擇:");scanf("%d", &input);switch (input){case 1:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("選擇錯誤\n");break;}} while (input);return 0;
}

這樣寫可讀性低,此時我們可以使用枚舉:
在這里插入圖片描述
在這里插入圖片描述

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

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

相關文章

K8s(Kubernetes)常用命令

大家好&#xff0c;當談及容器編排工具時&#xff0c;Kubernetes&#xff08;常簡稱為K8s&#xff09;無疑是當今最受歡迎和廣泛使用的解決方案之一。作為一個開源的容器編排平臺&#xff0c;Kubernetes 提供了豐富的功能&#xff0c;可以幫助開發人員和運維團隊管理、部署和擴…

電商分析@電商數據與運營優化

電商數據分析與運營優化是指通過對電商平臺的各種數據進行深入分析&#xff0c;以發現潛在的問題和機會&#xff0c;并采取相應的優化措施&#xff0c;提高電商運營效率和盈利能力。 首先&#xff0c;電商數據分析需要收集和整理各類數據&#xff0c;包括銷售數據、用戶數據、流…

大宋咨詢(深圳車主滿意度調查)如何開展汽車展會觀眾滿意度問卷調查

汽車展覽是由政府機構、專業協會或主流媒體等組織,在專業展館或會場中心進行的汽車產品展示展銷會或汽車行業經貿交易會、博覽會等活動。汽車展覽通過對汽車工藝的呈現與汽車產品的廣告,為消費者提供汽車制造工業與汽車產品的發展動向。同時,汽車廠商可通過汽車展覽對外宣傳產品…

實戰16:基于apriori關聯挖掘FP-growth算法挖掘關聯規則的手機銷售分析-代碼+數據

直接看視頻演示: 基于apriori關聯挖掘關聯規則的手機銷售分析與優化策略 直接看結果: 這是數據展示: 挖掘結果展示: 數據分析展示:

利用WK2168實現串口服務器

ESP32 SPI與WK2168實現串口服務器 概述系統組成代碼概述 一些老設備通過RS485采集數據,如果在一個系統中采用幾個RS485設備可能是一個不錯的選擇,但要是使用46個RS485數據采集設備為一個PLC提供外部數據,系統的性能就很難有保障了。通過一個串口服務器實現看來是一個好的選…

智慧校園有哪些特征

隨著科技的飛速進步&#xff0c;教育領域正經歷著一場深刻的變革。智慧校園&#xff0c;作為這場變革的前沿代表&#xff0c;正在逐步重塑我們的教育理念和實踐方式。它不僅僅是一個概念&#xff0c;而是一個集成了物聯網、大數據、人工智能等先進技術的綜合生態系統&#xff0…

SpringBoot源碼(自動裝配、內嵌Tomcat)

文章目錄 依賴管理pom依賴管理Web依賴自定義starter 一、WebMvcAutoConfiguration1.1 Filter1.2 Interceptor 二、源碼解析2.1 SpringApplication2.1.1 構造方法1、填充webApplicationType2、自動裝配Initializers3、自動裝配Listeners 2.1.2 run(args) 2.2 SpringApplicationR…

手寫Mitt實現事件訂閱、發布和取消訂閱

Mitt類設計 emitter屬性&#xff1a;用于存儲事件和對應的處理器 on方法&#xff1a;訂閱事件 off方法&#xff1a;取消訂閱事件 emit方法&#xff1a;觸發事件 export class Mitt<T> {private readonly emitter: Record<string, Array<(value: T[keyof T]) …

AI邊緣計算盒子在智慧交通的應用

方案背景 隨著經濟增長&#xff0c;交通出行需求大幅增長&#xff0c;但道路建設增長緩慢&#xff0c;交通供需矛盾日益顯著&#xff0c;中心城區主要道路高峰時段交通擁堵嚴重&#xff0c;道路交通擁堵逐漸常態化&#xff0c;成為制約城市可持續發展的重要因素之一。 痛點問題…

web 前端開發技術---網頁的制作

這是一個網頁代碼 上年包含了電子郵件&#xff0c;選項建 等等 分享給大家 <!-- prj_7_1.html --> <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><title>留言板設計</title><style type&…

【C++】入門(一):命名空間、缺省參數、函數重載

目錄 一、關鍵字 二、命名空間 問題引入(問題代碼)&#xff1a; 域的問題 1.::域作用限定符 的 用法&#xff1a; 2.域的分類 3.編譯器的搜索原則 命名空間的定義 命名空間的使用 舉個&#x1f330;栗子&#xff1a; 1.作用域限定符指定命名空間名稱 2. using 引入…

【數據結構與算法 | 堆篇】JAVA實現小頂堆

1. 堆的特點 堆的邏輯結構是數組&#xff0c;內存結構是完全二叉樹.完全二叉樹即只有最后一層才有葉子節點.堆又分為大頂堆與小頂堆. 大頂堆的特點是 : 父親節點比孩子節點的都要大. 小頂堆的特點與其相反.Java的優先級隊列(PriorityQueue)的底層實現即用到了小頂堆. 所以下文…

K210視覺識別模塊學習筆記3:內存卡寫入拍攝圖片_LED三色燈的操作_按鍵操作_定時器的配置使用

今日開始學習K210視覺識別模塊: LED三色燈的操作_按鍵操作_定時器的配置使用_內存卡寫入拍攝圖片 亞博智能的K210視覺識別模塊...... 本文最終目的是編寫一個按鍵拍照的例程序&#xff1a; 為以后的專用場景的模型訓練做準備&#xff0c;因為訓練自己的模型需要大量的圖片&a…

jmeter基礎入門練習題

jmeter存在A,B兩個線程組的情況下&#xff0c;默認設置下&#xff0c;運行順序是&#xff1a;A A&#xff1a;A,B同時運行 B&#xff1a;先運行A&#xff0c;在運行B C&#xff1a;先運行A&#xff0c;等待2s運行B D:先A運行完&#xff0c;等待默認設置時間后運行B 下列說法正…

編譯安裝PHP服務(LAMP3)

目錄 1.初始化設置&#xff0c;將安裝PHP所需軟件包傳到/opt目錄下 &#xff08;1&#xff09;關閉防火墻 &#xff08;2&#xff09;上傳軟件包到/opt目錄 2.安裝GD庫和GD庫關聯程序&#xff0c;用來處理和生成圖片 3.配置軟件模塊 4.編譯及安裝 5.優化把PHP 的可執行程…

nginx的安裝001

Nginx是一款高性能的HTTP和反向代理服務器&#xff0c;以及郵件代理服務器&#xff0c;由 Igor Sysoev 開發并公開發布于2004年。Nginx以其高并發處理能力、低內存消耗和穩定性著稱&#xff0c;特別適合部署在高流量的網站上。 操作系統&#xff1a; CentOS Stream 9 安裝步驟…

【算法訓練 day44 分割等和子集】

目錄 一、分割等和子集-LeetCode 416思路實現代碼1.二維dp代碼2.一維dp代碼 問題總結 一、分割等和子集-LeetCode 416 Leecode鏈接: leetcode 416 文章鏈接: 代碼隨想錄 視頻鏈接: B站 給你一個 只包含正整數 的 非空 數組 nums 。請你判斷是否可以將這個數組分割成兩個子集&…

SQL入門教程,很詳細

SQL&#xff08;Structured Query Language&#xff09;是一種用于管理關系數據庫的標準語言。它被廣泛用于存儲、操作和檢索數據。在這篇文章中&#xff0c;我們將介紹SQL的基本概念和常用命令。 首先&#xff0c;我們需要了解SQL的基本結構。SQL語句通常由以下幾個部分組成&…

頭歌數據結構與算法課程設計易-算式運算的合法性

給定一個算式運算&#xff0c;算式由運算數、、-、、/、(、)組成&#xff0c;請編寫程序判斷該算式運算是否合法。如果合法&#xff0c;計算該算式的值。 輸入描述&#xff1a; 第一行輸入一個運算表達式 輸出描述&#xff1a; 如果表達式合法則計算其值&#xff0c;結果保留兩…

c語言之向文件讀寫數據塊

c語言需要向文件讀寫數據塊需要用到fread語句和fwrite語句 fread語句的語法格式 fread(butter,size,count,fp) butter&#xff1a;讀取的數據存入內存地址 size:讀取的字節大小 count:讀取數據的個數 fp:讀取的文件指針 fwrite語句語法格式 fwrite(butter,size,count,fp…