C語言學習之十——共用體、枚舉類型和typedef

  1. 共用體
    1.1共用體的概念 :使幾個不同的變量共占同一段內存的結構,稱為“共用體”類型的結構。
    1.2 定義共用體類型變量的一般形式為:
    union 共用體名
    {
    成員表列
    }變量表列;

其實定義共用體變量有3中方法,其方法與定義結構體變量的3種方法類似:
1) 先聲明共用體類型再定義變量名

union date
{
int year;
int month;
long day;
};
union date d1, d2;

2)在定義結構體類型的同時定義變量
union 共用體名
{
成員列表
}變量名列表;

例:
union date
{
int year;
int month;
long day;
}d1, d2;

3) 直接定義共用體類型變量
union
{
成員列表
}變量名列表;

例:
union
{
int year;
int month;
long day;
}d1, d2;

1.3 共用體與結構體的比較
結構體變量所占內存長度是各成員占的內存長度之和,因為每個成員分別占有其自己的內存單元。共用體變量所占的內存長度等于最長的成員的長度,因為所用成員共享一個公共的內存單元,所以需要滿足最長成員的長度。見例1.

例如 : 上面定義的“共用體”變量d1、d2各占8個字節(因為在GCC中一個整型變量占4個字節,一個長整形變量占8個字節),而不是各占 4 +4+8=16個字節。

1.4 共用體變量的引用方式
只有先定義了共用體變量才能引用它,而且不能引用共用體變量,而只能引用共用體變量中的成員。
例如 : 前面定義了d1, d2為共用體變量
d1.year (引用共用體變量d1中的整型變量year)
d1.month(引用共用體變量d1中的字符變量month )
d1.day(引用共用體變量d1中的長整型變量day)

1.5 共用體類型數據的特點
1)同一個內存段可以用來存放幾種不同類型的成員,但在每一瞬時只能存放其中一種,而不是同時存放幾種。
2)共用體變量中起作用的成員是最后一次存放的成員,在存入一個新的成員后原有的成員就失去作用。
3)共用體變量的地址和它的各成員的地址都是同一地址。
(這3條特點共同說明了,所用共用體成員共享一個公共的內存單元)見例1.
4)不能對共用體變量名賦值,也不能企圖引用變量名來得到一個值,又不能在定義共用體變量時對它初始化。

5)不能把共用體變量作為函數參數,也不能使函數帶回共用體變量,但可以使用指向共用體變量的指針。
6)共用體類型可以出現在結構體類型定義中,也可以定義共用體數組。反之,結構體也可以出現在共用體類型定義中,數組也可以作為共用體的成員。見例2.

//例1.
/#include<stdio.h>

union date
{
int year;
int month;
long day;
}d1, d2;

void main()
{
d1.year = 2018;
d1.month = 01;
d1.day = 01;

printf("%d-%d-%ld\n", d1.year, d1.month, d1.day);
printf("&d1.year: %o, &d1.month: %o, &d1.day: %o\n", &d1.year, &d1.month, &d1.day);
printf("sizeof(d1): %d\n", sizeof(d1));

d1.year = 2018;
d1.month = 01;
d1.day = 02;

printf("%d-%d-%ld\n", d1.year, d1.month, d1.day);
printf("&d2.year: %o, &d2.month: %o, &d2.day: %o\n", &d2.year, &d2.month, &d2.day);
printf("sizeof(union date): %d\n", sizeof(union date));
}
//輸出:
1-1-1
&d1.year: 30010100, &d1.month: 30010100, &d1.day: 30010100
sizeof(d1): 8

2-2-2
&d2.year: 30010110, &d2.month: 30010110, &d2.day: 30010110
sizeof(union date): 8

//例2
/#include <stdio.h>

struct
{
int num;
char name[10];
char sex;
char job;
union
{
int banji;
char position[10];
}category;
}person[2]; //為了方便先假設一個學生一個老師。

void main()
{
int i;
for(i=0; i < 2; i++)
{
printf("Please input the num: ");
scanf("%d", &person[i].num);
printf("Please input the name: ");
scanf("%s", person[i].name);
fflush(stdin);
printf("Please input the sex(M/F): ");
scanf("%c", &person[i].sex);
fflush(stdin);
printf("Please input the job(s/t): ");
scanf("%c", &person[i].job);
fflush(stdin);
if( person[i].job == 's' )
{
printf("Please input the class: ");
scanf("%d", &person[i].category.banji);
fflush(stdin);
}
else if( person[i].job == 't' )
{
printf("Please input the position: ");
scanf("%s", person[i].category.position);
fflush(stdin);
}
else
{
printf("Input Error!!\n");
}
printf("\n");
}
printf("No. name sex job class/position\n");
for( i=0; i < 2; i++ )
{
if( person[i].job == 's')
{
printf("%-6d%-10s%-3c%-3c%10d\n", person[i].num,
person[i].name, person[i].sex, person[i].job,
person[i].category.banji);
}
else
{
printf("%-6d%-10s%-3c%-3c%10s\n", person[i].num,
person[i].name, person[i].sex, person[i].job,
person[i].category.position);
}
}
}

  1. 枚舉類型
    2.1 概念:在實際問題中,有些變量的取值被限定在一個有限的范圍內。例如,一個星期內只有七天,一年只有十二個月,一個班每周有六門課程等等。如果把這些量說明為整型,字符型或其它類型顯然是不妥當的。為此,C語言提供了一種稱為“枚舉”的類型。
    2.2 枚舉變量的聲明:設有變量 a,b,c 被說明為上述的 weekday ,可采
    用下述任一種方式:
    1)enum weekday{ sun,mou,tue,wed,thu,fri,sat };
    enum weekday a, b, c;

2)enum weekday{ sun,mou,tue,wed,thu,fri,sat }a, b, c;

3)enum { sun,mou,tue,wed,thu,fri,sat }a, b, c;

2.3 注意事項:
1)在“枚舉”類型的定義中列舉出所有可能的取值,被說明為該“枚舉”類型的變量取值不能超過定義的范圍。
2)枚舉類型是一種基本數據類型,而不是一種構造類型,因為它不能再分解為任何基本類型。
3)在枚舉值表中應羅列出所有可用值。這些值也稱為枚舉元素。
4)在C編譯中,對枚舉元素按常量處理,故稱枚舉常量。它們不是變量,不能對它們賦值。
5)枚舉元素作為常量,它們是有值的,C語言編譯按定義時的順序使它們的值為0,1,2...
6)枚舉值可以用來作判斷比較。
7)一個整數不能直接賦給一個枚舉變量。

//例3
/#include <stdio.h>

void main()
{
enum weekday{sun, mon, tue, wed, thu, fri, sat}a, b, c; /定義枚舉類型weekday,并聲明枚舉變量a, b, c/
a = 1; // a = 1;這樣是不行的,因為這里是用一個整形的1來覆蓋a所代表的 enum
b = mon;
c = sat;
printf("%d, %d, %d", a, b, c);
printf("\n\n");
}
//輸出: 1, 1, 6

//例4
/#include <stdio.h>

void main()
{
enum boy{Tom, Danny, Gan, LiLei}month[31], j;
int i;
j = Tom;
for( i=1; i <= 30; i++ )
{
month[i] = j;
j++;
if( j > LiLei )
{
j = Tom;
}
}
for( i=1; i <= 30; i++)
{
switch( month[i] )
{
case Tom: printf(" %4d %s\t", i, "Tom");
break;
case Danny: printf(" %4d %s\t", i, "Danny");
break;
case Gan: printf(" %4d %s\t", i, "Gan");
break;
case LiLei: printf(" %4d %s\t", i, "LiLei");
break;
default:
break;
}
}
printf("\n");
}
//輸出:
1 Tom 2 Danny 3 Gan 4 LiLei 5 Tom
6 Danny 7 Gan 8 LiLei 9 Tom 10 Danny
11 Gan 12 LiLei 13 Tom 14 Danny 15 Gan
16 LiLei 17 Tom 18 Danny 19 Gan 20 LiLei
21 Tom 22 Danny 23 Gan 24 LiLei 25 Tom
26 Danny 27 Gan 28 LiLei 29 Tom 30 Danny

  1. typedef
    3.1 typedef的作用:用 typedef 聲明新的類型名來代替已有的類型名
    3.2 用 typedef 定義類型
    1)聲明 INTEGER 為整型:“typedef int INTEGER;” 見例5

//例5
/#include <stdio.h>
typedef int INTEGER;

void main()
{
INTEGER i = 1;
int j = 2;
printf("%d, %d\n", i, j);
}
//輸出:1, 2

2)聲明結構類型

Typedef struct
{
int month ;
int day ;
int year ;
}DATE;

//例6
/#include <stdio.h>
typedef struct
{
int month;
int day;
int year;
}DATE;
void main()
{
DATE date_one;
date_one.month = 12;
date_one.day = 31;
date_one.year = 2017;
printf("%d - %d - %d \n", date_one.year, date_one.month, date_one.day);
}
//輸出: 2017-12-31

3)聲明NUM為整型數組類型:“typedef int NUM[100];” 見例7.

//例7
/#include <stdio.h>

typedef int NUM[100];

void main()
{
NUM num = {0};
printf("%d\n", sizeof(num));
}
//輸出:400

4)聲明STRING為字符指針類型:“typedef char* STRING ;”見例8.

//例8.
/#include <stdio.h>

typedef char* P; //聲明字符指針類型P

void main()
{
P p1;
p1 = "I love UNSW";
printf("%s\n", p1);
}
//輸出: I love UNSW

5)聲明P為函數指針類型:“typedef void (*P)();”見例9

//例9
/#include <stdio.h>

typedef void (*P)(); //聲明函數指針類型P

void fun();
void main()
{
P p1; // 這里的p1等價于“void (*p1)();”即定義p1為函數指針類型P的實參
p1 = fun; //將函數fun()的入口地址賦給指針變量p1
( * p1)(); //函數指針通過調用函數實現輸出
}

void fun()
{
printf("I love UNSW\n");
}
//輸出:I love UNSW

3.3 用 typedef 定義類型的方法
1)按定義變量的方法寫出定義體(如: int i )
2)將變量名換成新類型名(例如:將 i 換成 COUNT )。
3)在最前面加typedef (例如: typedef int COUNT )
4)然后可以用新類型名去定義變量(例如: COUNT i,j;)

3.2 關于typedef的說明
1)用 typedef 可以聲明各種類型名,但不能用來定義變量。
2)用 typedef 只是對已經存在的類型增加一個類型名,而沒有創造新的類型。
3)當不同源文件中用到同一類型數據時,常用 typedef 聲明一些數據類型,把它們單獨放在一個文件中,然后在需要用到它們的文件中用 #include命令把它們包含進來。
4)使用 typedef 有利于程序的通用與移植。

3.1 typedef 與 #define 的比較
相似:typedef 與 #define 有相似之處,例如: typedef int COUNT ; #define COUNT int 的作用都是用 COUNT 代表 int 。

區別:#define 是在預編譯時處理的,它只能作簡單的字符串替換,而 typedef 是在編譯時處理的。實際上它并不是作簡單的字符串替換,而是采用如同定義變量的方法那樣來聲明一個類型。
另外注意,“typedef (int * ) p1;”和“#define p2 int*” 一個有分號,一個沒有分號

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容