- 共用體
1.1共用體的概念 :使幾個(gè)不同的變量共占同一段內(nèi)存的結(jié)構(gòu),稱為“共用體”類型的結(jié)構(gòu)。
1.2 定義共用體類型變量的一般形式為:
union 共用體名
{
成員表列
}變量表列;
其實(shí)定義共用體變量有3中方法,其方法與定義結(jié)構(gòu)體變量的3種方法類似:
1) 先聲明共用體類型再定義變量名
union date
{
int year;
int month;
long day;
};
union date d1, d2;
2)在定義結(jié)構(gòu)體類型的同時(shí)定義變量
union 共用體名
{
成員列表
}變量名列表;
例:
union date
{
int year;
int month;
long day;
}d1, d2;
3) 直接定義共用體類型變量
union
{
成員列表
}變量名列表;
例:
union
{
int year;
int month;
long day;
}d1, d2;
1.3 共用體與結(jié)構(gòu)體的比較
結(jié)構(gòu)體變量所占內(nèi)存長度是各成員占的內(nèi)存長度之和,因?yàn)槊總€(gè)成員分別占有其自己的內(nèi)存單元。共用體變量所占的內(nèi)存長度等于最長的成員的長度,因?yàn)樗贸蓡T共享一個(gè)公共的內(nèi)存單元,所以需要滿足最長成員的長度。見例1.
例如 : 上面定義的“共用體”變量d1、d2各占8個(gè)字節(jié)(因?yàn)樵贕CC中一個(gè)整型變量占4個(gè)字節(jié),一個(gè)長整形變量占8個(gè)字節(jié)),而不是各占 4 +4+8=16個(gè)字節(jié)。
1.4 共用體變量的引用方式
只有先定義了共用體變量才能引用它,而且不能引用共用體變量,而只能引用共用體變量中的成員。
例如 : 前面定義了d1, d2為共用體變量
d1.year (引用共用體變量d1中的整型變量year)
d1.month(引用共用體變量d1中的字符變量month )
d1.day(引用共用體變量d1中的長整型變量day)
1.5 共用體類型數(shù)據(jù)的特點(diǎn)
1)同一個(gè)內(nèi)存段可以用來存放幾種不同類型的成員,但在每一瞬時(shí)只能存放其中一種,而不是同時(shí)存放幾種。
2)共用體變量中起作用的成員是最后一次存放的成員,在存入一個(gè)新的成員后原有的成員就失去作用。
3)共用體變量的地址和它的各成員的地址都是同一地址。
(這3條特點(diǎn)共同說明了,所用共用體成員共享一個(gè)公共的內(nèi)存單元)見例1.
4)不能對共用體變量名賦值,也不能企圖引用變量名來得到一個(gè)值,又不能在定義共用體變量時(shí)對它初始化。
5)不能把共用體變量作為函數(shù)參數(shù),也不能使函數(shù)帶回共用體變量,但可以使用指向共用體變量的指針。
6)共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,也可以定義共用體數(shù)組。反之,結(jié)構(gòu)體也可以出現(xiàn)在共用體類型定義中,數(shù)組也可以作為共用體的成員。見例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): 82-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]; //為了方便先假設(shè)一個(gè)學(xué)生一個(gè)老師。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);
}
}
}
- 枚舉類型
2.1 概念:在實(shí)際問題中,有些變量的取值被限定在一個(gè)有限的范圍內(nèi)。例如,一個(gè)星期內(nèi)只有七天,一年只有十二個(gè)月,一個(gè)班每周有六門課程等等。如果把這些量說明為整型,字符型或其它類型顯然是不妥當(dāng)?shù)?。為?C語言提供了一種稱為“枚舉”的類型。
2.2 枚舉變量的聲明:設(shè)有變量 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 注意事項(xiàng):
1)在“枚舉”類型的定義中列舉出所有可能的取值,被說明為該“枚舉”類型的變量取值不能超過定義的范圍。
2)枚舉類型是一種基本數(shù)據(jù)類型,而不是一種構(gòu)造類型,因?yàn)樗荒茉俜纸鉃槿魏位绢愋汀?br>
3)在枚舉值表中應(yīng)羅列出所有可用值。這些值也稱為枚舉元素。
4)在C編譯中,對枚舉元素按常量處理,故稱枚舉常量。它們不是變量,不能對它們賦值。
5)枚舉元素作為常量,它們是有值的,C語言編譯按定義時(shí)的順序使它們的值為0,1,2...
6)枚舉值可以用來作判斷比較。
7)一個(gè)整數(shù)不能直接賦給一個(gè)枚舉變量。
//例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;這樣是不行的,因?yàn)檫@里是用一個(gè)整形的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
- 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)聲明結(jié)構(gòu)類型
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為整型數(shù)組類型:“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為函數(shù)指針類型:“typedef void (*P)();”見例9
//例9
/#include <stdio.h>typedef void (*P)(); //聲明函數(shù)指針類型P
void fun();
void main()
{
P p1; // 這里的p1等價(jià)于“void (*p1)();”即定義p1為函數(shù)指針類型P的實(shí)參
p1 = fun; //將函數(shù)fun()的入口地址賦給指針變量p1
( * p1)(); //函數(shù)指針通過調(diào)用函數(shù)實(shí)現(xiàn)輸出
}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 關(guān)于typedef的說明
1)用 typedef 可以聲明各種類型名,但不能用來定義變量。
2)用 typedef 只是對已經(jīng)存在的類型增加一個(gè)類型名,而沒有創(chuàng)造新的類型。
3)當(dāng)不同源文件中用到同一類型數(shù)據(jù)時(shí),常用 typedef 聲明一些數(shù)據(jù)類型,把它們單獨(dú)放在一個(gè)文件中,然后在需要用到它們的文件中用 #include命令把它們包含進(jìn)來。
4)使用 typedef 有利于程序的通用與移植。
3.1 typedef 與 #define 的比較
相似:typedef 與 #define 有相似之處,例如: typedef int COUNT ; #define COUNT int 的作用都是用 COUNT 代表 int 。
區(qū)別:#define 是在預(yù)編譯時(shí)處理的,它只能作簡單的字符串替換,而 typedef 是在編譯時(shí)處理的。實(shí)際上它并不是作簡單的字符串替換,而是采用如同定義變量的方法那樣來聲明一個(gè)類型。
另外注意,“typedef (int * ) p1;”和“#define p2 int*” 一個(gè)有分號,一個(gè)沒有分號