C語言共用體(Union)


結構體和共用體的區別在於:結構體的各個成員會占用不同的內存,互相之間沒有影響;而共用體的所有成員占用同一段內存,修改一個成員會影響其余所有成員。

結構體占用的內存大於等於所有成員占用的內存的總和(成員之間可能會存在縫隙),共用體占用的內存等於最長的成員占用的內存。共用體使用了內存覆蓋技術,同一時刻只能保存一個成員的值,如果對新的成員賦值,就會把原來成員的值覆蓋掉。

共用體也是一種自定義類型,可以通過它來創建變量,例如:

  1. union data{
  2. int n;
  3. char ch;
  4. double f;
  5. };
  6. union data a, b, c;

上面是先定義共用體,再創建變量,也可以在定義共用體的同時創建變量:

  1. union data{
  2. int n;
  3. char ch;
  4. double f;
  5. } a, b, c;

如果不再定義新的變量,也可以將共用體的名字省略:

  1. union{
  2. int n;
  3. char ch;
  4. double f;
  5. } a, b, c;

共用體 data 中,成員 f 占用的內存最多,為 8 個字節,所以 data 類型的變量(也就是 a、b、c)也占用 8 個字節的內存,請看下面的演示:

  1. #include <stdio.h>
  2. union data{
  3. int n;
  4. char ch;
  5. short m;
  6. };
  7. int main(){
  8. union data a;
  9. printf("%d, %d\n", sizeof(a), sizeof(union data) );
  10. a.n = 0x40;
  11. printf("%X, %c, %hX\n", a.n, a.ch, a.m);
  12. a.ch = '9';
  13. printf("%X, %c, %hX\n", a.n, a.ch, a.m);
  14. a.m = 0x2059;
  15. printf("%X, %c, %hX\n", a.n, a.ch, a.m);
  16. a.n = 0x3E25AD54;
  17. printf("%X, %c, %hX\n", a.n, a.ch, a.m);
  18. return 0;
  19. }

運行結果:

4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54

這段代碼不但驗證了共用體的長度,還說明共用體成員之間會相互影響,修改一個成員的值會影響其他成員。

要想理解上面的輸出結果,弄清成員之間究竟是如何相互影響的,就得了解各個成員在內存中的分布。以上面的 data 為例,各個成員在內存中的分布如下:

成員 n、ch、m 在內存中“對齊”到一頭,對 ch 賦值修改的是前一個字節,對 m 賦值修改的是前兩個字節,對 n 賦值修改的是全部字節。也就是說,ch、m 會影響到 n 的一部分數據,而 n 會影響到 ch、m 的全部數據。

上圖是在絕大多數 PC 機上的內存分布情況,如果是 51 單片機,情況就會有所不同:

為什么不同的機器會有不同的分布情況呢?這跟機器的存儲模式有關,我們將在VIP教程《大端小端以及判別方式》一節中展開探討。

共用體的應用

共用體在一般的編程中應用較少,在單片機中應用較多。對於 PC 機,經常使用到的一個實例是: 現有一張關於學生信息和教師信息的表格。學生信息包括姓名、編號、性別、職業、分數,教師的信息包括姓名、編號、性別、職業、教學科目。請看下面的表格:

Name Num Sex Profession Score / Course
HanXiaoXiao 501 f s 89.5
YanWeiMin 1011 m t math
LiuZhenTao 109 f t English
ZhaoFeiYan 982 m s 95.0


f 和 m 分別表示女性和男性,s 表示學生,t 表示教師。可以看出,學生和教師所包含的數據是不同的。現在要求把這些信息放在同一個表格中,並設計程序輸入人員信息然后輸出。

如果把每個人的信息都看作一個結構體變量的話,那么教師和學生的前 4 個成員變量是一樣的,第 5 個成員變量可能是 score 或者 course。當第 4 個成員變量的值是 s 的時候,第 5 個成員變量就是 score;當第 4 個成員變量的值是 t 的時候,第 5 個成員變量就是 course。

經過上面的分析,我們可以設計一個包含共用體的結構體,請看下面的代碼:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define TOTAL 4 //人員總數
  4. struct{
  5. char name[20];
  6. int num;
  7. char sex;
  8. char profession;
  9. union{
  10. float score;
  11. char course[20];
  12. } sc;
  13. } bodys[TOTAL];
  14. int main(){
  15. int i;
  16. //輸入人員信息
  17. for(i=0; i<TOTAL; i++){
  18. printf("Input info: ");
  19. scanf("%s %d %c %c", bodys[i].name, &(bodys[i].num), &(bodys[i].sex), &(bodys[i].profession));
  20. if(bodys[i].profession == 's'){ //如果是學生
  21. scanf("%f", &bodys[i].sc.score);
  22. }else{ //如果是老師
  23. scanf("%s", bodys[i].sc.course);
  24. }
  25. fflush(stdin);
  26. }
  27. //輸出人員信息
  28. printf("\nName\t\tNum\tSex\tProfession\tScore / Course\n");
  29. for(i=0; i<TOTAL; i++){
  30. if(bodys[i].profession == 's'){ //如果是學生
  31. printf("%s\t%d\t%c\t%c\t\t%f\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.score);
  32. }else{ //如果是老師
  33. printf("%s\t%d\t%c\t%c\t\t%s\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.course);
  34. }
  35. }
  36. return 0;
  37. }

運行結果:

Input info: HanXiaoXiao 501 f s 89.5↙
Input info: YanWeiMin 1011 m t math↙
Input info: LiuZhenTao 109 f t English↙
Input info: ZhaoFeiYan 982 m s 95.0↙

Name            Num     Sex     Profession      Score / Course
HanXiaoXiao     501     f       s               89.500000
YanWeiMin       1011    m       t               math
LiuZhenTao      109     f       t               English
ZhaoFeiYan      982     m       s               95.000000


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM