網(wǎng)站首頁
分類導(dǎo)航
試題中心
下載中心
英語學(xué)習(xí)
繽紛校園
考試論壇
網(wǎng)站留言
客服中心
 C教程連載--第四章 指針、結(jié)構(gòu)、聯(lián)合和枚舉
【字體:
C教程連載--第四章 指針、結(jié)構(gòu)、聯(lián)合和枚舉
http://m.1glr.cn 來源:考試吧(Exam8.com) 點(diǎn)擊: 更新:2004-8-16

第四章  指針、結(jié)構(gòu)、聯(lián)合和枚舉

    本章專門對第二節(jié)曾講述過的指針作一詳述。并介紹Turbo C新的數(shù)據(jù)類型:
結(jié)構(gòu)、聯(lián)合和枚舉, 其中結(jié)構(gòu)和聯(lián)合是以前講過的五種基本數(shù)據(jù)類型(整型、浮
點(diǎn)型、字符型、指針型和無值型)的組合。 枚舉是一個被命名為整型常數(shù)的集合。
最后對類型說明(typedef)和預(yù)處理指令作一闡述。

                    指         針(point)

    學(xué)習(xí)Turbo C語言, 如果你不能用指針編寫有效、正確和靈活的程序,  可以
認(rèn)為你沒有學(xué)好C語言。指針、地址、數(shù)組及其相互關(guān)系是C語言中最有特色的部
分。規(guī)范地使用指針, 可以使程序達(dá)到簡單明了, 因此, 我們不但要學(xué)會如何正
確地使用指針, 而且要學(xué)會在各種情況下正確地使用指針變量。

    1. 指針和地址
    1.1 指針基本概念及其指針變量的定義
    1.1.1 指針變量的定義
    我們知道變量在計算機(jī)內(nèi)是占有一塊存貯區(qū)域的, 變量的值就存放在這塊區(qū)
域之中, 在計算機(jī)內(nèi)部, 通過訪問或修改這塊區(qū)域的內(nèi)容來訪問或修改相應(yīng)的變
量。Turbo C語言中, 對于變量的訪問形式之一, 就是先求出變量的地址,  然后
再通過地址對它進(jìn)行訪問, 這就是這里所要論述的指針及其指針變量。
    所謂變量的指針, 實(shí)際上指變量的地址。變量的地址雖然在形式上好象類似
于整數(shù), 但在概念上不同于以前介紹過的整數(shù), 它屬于一種新的數(shù)據(jù)類型, 即指
針類型。Turbo C中, 一般用"指針"來指明這樣一個表達(dá)式&x的類型,  而用 "地
址"作為它的值, 也就是說, 若x為一整型變量, 則表達(dá)式&x的類型是指向整數(shù)的
指針, 而它的值是變量x的地址。同樣, 若
     double d;
則&d的類型是指向以精度數(shù)d的指針, 而&d的值是雙精度變量d的地址。所以, 指
針和地址是用來敘述一個對象的兩個方面。雖然&x、&d的值分別是整型變量x 和
雙精度變量d的地址, 但&x、&d的類型是不同的, 一個是指向整型變量x的指針,
而另一個則是指向雙精度變量d的指針。在習(xí)慣上,  很多情況下指針和地址這兩
個術(shù)語混用了。
    我們可以用下述方法來定義一個指針類型的變量。
     int *ip;
首先說明了它是一指針類型的變量, 注意在定義中不要漏寫符號"*",  否則它為
一般的整型變量了。另外, 在定義中的int 表示該指針變量為指向整型數(shù)的指針
類型的變量, 有時也可稱ip為指向整數(shù)的指針。ip是一個變量, 它專門存放整型
變量的地址。
    指針變量的一般定義為:
     類型標(biāo)識符  *標(biāo)識符;
    其中標(biāo)識符是指針變量的名字, 標(biāo)識符前加了"*"號,  表示該變量是指針變
量, 而最前面的"類型標(biāo)識符"表示該指針變量所指向的變量的類型。一個指針變
量只能指向同一種類型的變量, 也就是講, 我們不能定義一個指針變量, 既能指
向一整型變量又能指向雙精度變量。
    指針變量在定義中允許帶初始化項。如:
      int i, *ip=&i;
注意, 這里是用&i對ip初始化, 而不是對*ip初始化。和一般變量一樣,  對于外
部或靜態(tài)指針變量在定義中若不帶初始化項, 指針變量被初始化為NULL, 它的值
為0。Turbo C中規(guī)定, 當(dāng)指針值為零時, 指針不指向任何有效數(shù)據(jù), 有時也稱指
針為空指針。因此, 當(dāng)調(diào)用一個要返回指針的函數(shù)(第五節(jié)中介紹)時, 常使用返
回值為NULL來指示函數(shù)調(diào)用中某些錯誤情況的發(fā)生。 

    1.1.2 指針變量的引用
    既然在指針變量中只能存放地址, 因此, 在使用中不要將一個整數(shù)賦給一指
針變量。下面的賦值是不合法的:
     int *ip;
     ip=100;
假設(shè)
     int i=200, x;
     int *ip;
我們定義了兩個整型變量i, x, 還定義了一個指向整型數(shù)的指針變量ip。i, x中
可存放整數(shù), 而ip中只能存放整型變量的地址。我們可以把i的地址賦給ip:
     ip=&i;
此時指針變量ip指向整型變量i, 假設(shè)變量i的地址為1800, 這個賦值可形象理解
為下圖所示的聯(lián)系。
            ip               i
        ┏━━━┓       ┏━━━┓
        ┃ 1800 ╂──→ ┃ 200  ┃
        ┗━━━┛       ┗━━━┛
            圖1. 給指針變量賦值
以后我們便可以通過指針變量ip間接訪問變量i, 例如:
     x=*ip;
運(yùn)算符*訪問以ip為地址的存貯區(qū)域, 而ip中存放的是變量i的地址, 因此, *ip
訪問的是地址為1800的存貯區(qū)域(因為是整數(shù), 實(shí)際上是從1800開始的兩個字節(jié)),
它就是i所占用的存貯區(qū)域, 所以上面的賦值表達(dá)式等價于
     x=i;
    另外, 指針變量和一般變量一樣, 存放在它們之中的值是可以改變的, 也就
是說可以改變它們的指向, 假設(shè)
     int i, j, *p1, *p2;
     i='a';
     j='b';
     p1=&i;
     p2=&j;
則建立如下圖所示的聯(lián)系:
            p1               i
        ┏━━━┓       ┏━━━┓
        ┃      ╂──→ ┃ 'a'  ┃
        ┗━━━┛       ┗━━━┛
            p2               i
        ┏━━━┓       ┏━━━┓
        ┃      ╂──→ ┃ 'b'  ┃
        ┗━━━┛       ┗━━━┛
             圖2. 賦值運(yùn)算結(jié)果
這時賦值表達(dá)式:
     p2=p1
就使p2與p1指向同一對象i, 此時*p2就等價于i, 而不是j, 圖2.就變成圖3.所示:
            p1               i
        ┏━━━┓       ┏━━━┓
        ┃      ╂──→ ┃ 'a'  ┃
        ┗━━━┛  ┌→ ┗━━━┛
            p2      │       j
        ┏━━━┓  │   ┏━━━┓
        ┃      ╂─┘   ┃ 'b'  ┃
        ┗━━━┛       ┗━━━┛
            圖3. p2=p1時的情形
如果執(zhí)行如下表達(dá)式:
     *p2=*p1;
則表示把p1指向的內(nèi)容賦給p2所指的區(qū)域, 此時圖2.就變成圖4.所示
            p1               i
        ┏━━━┓       ┏━━━┓
        ┃      ╂──→ ┃ 'a'  ┃
        ┗━━━┛       ┗━━━┛
            p2               j
        ┏━━━┓       ┏━━━┓
        ┃      ╂──→ ┃ 'a'  ┃
        ┗━━━┛       ┗━━━┛
            圖4. *p2=*p1時的情形
    通過指針訪問它所指向的一個變量是以間接訪問的形式進(jìn)行的, 所以比直接
訪問一個變量要費(fèi)時間, 而且不直觀, 因為通過指針要訪問哪一個變量, 取決于
指針的值(即指向), 例如"*p2=*p1;"實(shí)際上就是"j=i;", 前者不僅速度慢而且目
的不明。但由于指針是變量, 我們可以通過改變它們的指向, 以間接訪問不同的
變量, 這給程序員帶來靈活性, 也使程序代碼編寫得更為簡潔和有效。
    指針變量可出現(xiàn)在表達(dá)式中, 設(shè)
     int x, y *px=&x;
指針變量px指向整數(shù)x, 則*px可出現(xiàn)在x能出現(xiàn)的任何地方。例如:
     y=*px+5;  /*表示把x的內(nèi)容加5并賦給y*/
     y=++*px;  /*px的內(nèi)容加上1之后賦給y  [++*px相當(dāng)于++(px)]*/
     y=*px++;  /*相當(dāng)于y=*px; px++*/

    1.2. 地址運(yùn)算
    指針允許的運(yùn)算方式有:
    (1). 指針在一定條件下, 可進(jìn)行比較, 這里所說的一定條件,  是指兩個指
針指向同一個對象才有意義, 例如兩個指針變量p, q指向同一數(shù)組, 則<, >, >=,
<=, ==等關(guān)系運(yùn)算符都能正常進(jìn)行。若p==q為真, 則表示p, q指向數(shù)組的同一元
素; 若p12)?name[0]:name[n]);
     }
     main()
     {
          int i;
          for(i=0; i<13; i++)
               printf("%s\n", month_name(i));

     }

                    結(jié)         構(gòu)(struct)
    結(jié)構(gòu)是由基本數(shù)據(jù)類型構(gòu)成的、并用一個標(biāo)識符來命名的各種變量的組合。
結(jié)構(gòu)中可以使用不同的數(shù)據(jù)類型。

    1. 結(jié)構(gòu)說明和結(jié)構(gòu)變量定義
    在Turbo C中, 結(jié)構(gòu)也是一種數(shù)據(jù)類型, 可以使用結(jié)構(gòu)變量, 因此,  象其它
類型的變量一樣, 在使用結(jié)構(gòu)變量時要先對其定義。
    定義結(jié)構(gòu)變量的一般格式為:
     struct 結(jié)構(gòu)名
     {
          類型  變量名;
          類型  變量名;
          ...
     } 結(jié)構(gòu)變量;
    結(jié)構(gòu)名是結(jié)構(gòu)的標(biāo)識符不是變量名。
    類型為第二節(jié)中所講述的五種數(shù)據(jù)類型(整型、浮點(diǎn)型、字符型、指針型和
無值型)。
    構(gòu)成結(jié)構(gòu)的每一個類型變量稱為結(jié)構(gòu)成員, 它象數(shù)組的元素一樣, 但數(shù)組中
元素是以下標(biāo)來訪問的, 而結(jié)構(gòu)是按變量名字來訪問成員的。
    下面舉一個例子來說明怎樣定義結(jié)構(gòu)變量。
     struct string
     {
          char name[8];
          int age;
          char sex[2];
          char depart[20];
          float wage1, wage2, wage3, wage4, wage5;
     } person;
    這個例子定義了一個結(jié)構(gòu)名為string的結(jié)構(gòu)變量person,   如果省略變量名
person, 則變成對結(jié)構(gòu)的說明。用已說明的結(jié)構(gòu)名也可定義結(jié)構(gòu)變量。這樣定義
時上例變成:
     struct string
     {
          char name[8];
          int age;
          char sex[2];
          char depart[20];
          float wage1, wage2, wage3, wage4, wage5;
     };
     struct string person;
    如果需要定義多個具有相同形式的結(jié)構(gòu)變量時用這種方法比較方便, 它先作
結(jié)構(gòu)說明, 再用結(jié)構(gòu)名來定義變量。
    例如:
     struct string Tianyr, Liuqi, ...;
    如果省略結(jié)構(gòu)名, 則稱之為無名結(jié)構(gòu), 這種情況常常出現(xiàn)在函數(shù)內(nèi)部, 用這
種結(jié)構(gòu)時前面的例子變成:
     struct
     {
          char name[8];
          int age;
          char sex[2];
          char depart[20];
          float wage1, wage2, wage3, wage4, wage5;
     } Tianyr, Liuqi;

    2. 結(jié)構(gòu)變量的使用
    結(jié)構(gòu)是一個新的數(shù)據(jù)類型, 因此結(jié)構(gòu)變量也可以象其它類型的變量一樣賦值、
運(yùn)算, 不同的是結(jié)構(gòu)變量以成員作為基本變量。
    結(jié)構(gòu)成員的表示方式為:
          結(jié)構(gòu)變量.成員名
    如果將"結(jié)構(gòu)變量.成員名"看成一個整體,  則這個整體的數(shù)據(jù)類型與結(jié)構(gòu)中
該成員的數(shù)據(jù)類型相同, 這樣就可象前面所講的變量那樣使用。
    下面這個例子定義了一個結(jié)構(gòu)變量, 其中每個成員都從鍵盤接收數(shù)據(jù), 然后
對結(jié)構(gòu)中的浮點(diǎn)數(shù)求和, 并顯示運(yùn)算結(jié)果, 同時將數(shù)據(jù)以文本方式存入一個名為
wage.dat的磁盤文件中。請注意這個例子中不同結(jié)構(gòu)成員的訪問。
    例3:
     #include
     main()
     {
          struct{                  /*定義一個結(jié)構(gòu)變量*/
               char name[8];
               int age;
               char sex[2];
               char depart[20];
               float wage1, wage2, wage3, wage4, wage5;
          }a;
          FILE *fp;
          float wage;
          char c='Y';
          fp=fopen("wage.dat", "w");    /*創(chuàng)建一個文件只寫*/
          while(c=='Y'||c=='y')         /*判斷是否繼續(xù)循環(huán)*/
          {
               printf("\nName:");
               scanf("%s", a.name);     /*輸入姓名*/
               printf("Age:");
               scanf("%d", &a.wage);    /*輸入年齡*/
               printf("Sex:");
               scanf("%d", a.sex);
               printf("Dept:");
               scanf("%s", a.depart);
               printf("Wage1:");
               scanf("%f", &a.wage1);   /*輸入工資*/
               printf("Wage2:");
               scanf("%f", &a.wage2);
               printf("Wage3:");
               scanf("%f", &a.wage3);
               printf("Wage4:");
               scanf("%f", &a.wage4);
               printf("Wage5:");
               scanf("%f", &a.wage5);
               wage=a.wage1+a.wage2+a.wage3+a.wage4+a.wage5;
               printf("The sum of wage is %6.2f\n", wage);/*顯示結(jié)果*/
               fprintf(fp, "%10s%4d%4s%30s%10.2f\n",  /*結(jié)果寫入文件*/
                            a.name, a.age, a.sex, a.depart, wage);
               while(1)
               {
                    printf("Continue?");
                    c=getche();
                    if(c=='Y'||c=='y'||c=='N'||c=='n')
                         break;
               }
          }
          fclose(fp);
     }

    3. 結(jié)構(gòu)數(shù)組和結(jié)構(gòu)指針
    結(jié)構(gòu)是一種新的數(shù)據(jù)類型, 同樣可以有結(jié)構(gòu)數(shù)組和結(jié)構(gòu)指針。
    一、結(jié)構(gòu)數(shù)組
    結(jié)構(gòu)數(shù)組就是具有相同結(jié)構(gòu)類型的變量集合。假如要定義一個班級40個同學(xué)
的姓名、性別、年齡和住址, 可以定義成一個結(jié)構(gòu)數(shù)組。如下所示:
     struct{
          char name[8];
          char sex[2];
          int age;
          char addr[40];
     }student[40];
    也可定義為:
     struct string{
          char name[8];
          char sex[2];
          int age;
          char addr[40];
     };
     struct string student[40];
    需要指出的是結(jié)構(gòu)數(shù)組成員的訪問是以數(shù)組元素為結(jié)構(gòu)變量的, 其形式為:
          結(jié)構(gòu)數(shù)組元素.成員名
    例如:
      student[0].name
      student[30].age
    實(shí)際上結(jié)構(gòu)數(shù)組相當(dāng)于一個二維構(gòu)造, 第一維是結(jié)構(gòu)數(shù)組元素, 每個元素是
一個結(jié)構(gòu)變量, 第二維是結(jié)構(gòu)成員。
    注意:
    結(jié)構(gòu)數(shù)組的成員也可以是數(shù)組變量。
    例如:
     struct a
     {
          int m[3][5];
          float f;
          char s[20];
     }y[4];
    為了訪問結(jié)構(gòu)a中結(jié)構(gòu)變量y[2]的這個變量, 可寫成
       y[2].m[1][4]

    二、結(jié)構(gòu)指針
    結(jié)構(gòu)指針是指向結(jié)構(gòu)的指針。它由一個加在結(jié)構(gòu)變量名前的"*" 操作符來定
義, 例如用前面已說明的結(jié)構(gòu)定義一個結(jié)構(gòu)指針如下:
     struct string{
          char name[8];
          char sex[2];
          int age;
          char addr[40];
     }*student;
    也可省略結(jié)構(gòu)指針名只作結(jié)構(gòu)說明, 然后再用下面的語句定義結(jié)構(gòu)指針。
      struct string *student;
    使用結(jié)構(gòu)指針對結(jié)構(gòu)成員的訪問, 與結(jié)構(gòu)變量對結(jié)構(gòu)成員的訪問在表達(dá)方式
上有所不同。結(jié)構(gòu)指針對結(jié)構(gòu)成員的訪問表示為:
       結(jié)構(gòu)指針名->結(jié)構(gòu)成員
    其中"->"是兩個符號"-"和">"的組合, 好象一個箭頭指向結(jié)構(gòu)成員。例如要
給上面定義的結(jié)構(gòu)中name和age賦值, 可以用下面語句:
     strcpy(student->name, "Lu G.C");
     student->age=18;
    實(shí)際上, student->name就是(*student).name的縮寫形式。
    需要指出的是結(jié)構(gòu)指針是指向結(jié)構(gòu)的一個指針, 即結(jié)構(gòu)中第一個成員的首地
址, 因此在使用之前應(yīng)該對結(jié)構(gòu)指針初始化, 即分配整個結(jié)構(gòu)長度的字節(jié)空間,
這可用下面函數(shù)完成, 仍以上例來說明如下:
     student=(struct string*)malloc(size of (struct string));
    size of (struct string)自動求取string結(jié)構(gòu)的字節(jié)長度, malloc() 函數(shù)
定義了一個大小為結(jié)構(gòu)長度的內(nèi)存區(qū)域, 然后將其詐地址作為結(jié)構(gòu)指針返回。

    注意:
    1. 結(jié)構(gòu)作為一種數(shù)據(jù)類型,  因此定義的結(jié)構(gòu)變量或結(jié)構(gòu)指針變量同樣有局
部變量和全程變量, 視定義的位置而定。
    2. 結(jié)構(gòu)變量名不是指向該結(jié)構(gòu)的地址, 這與數(shù)組名的含義不同,  因此若需
要求結(jié)構(gòu)中第一個成員的首地址應(yīng)該是&[結(jié)構(gòu)變量名]。
    4. 結(jié)構(gòu)的復(fù)雜形式
    一、嵌套結(jié)構(gòu)
    嵌套結(jié)構(gòu)是指在一個結(jié)構(gòu)成員中可以包括其它一個結(jié)構(gòu), Turbo C 允許這種
嵌套。
    例如: 下面是一個有嵌套的結(jié)構(gòu)
     struct string{
          char name[8];
          int age;
          struct addr address;
     } student;
    其中: addr為另一個結(jié)構(gòu)的結(jié)構(gòu)名, 必須要先進(jìn)行, 說明, 即
     struct addr{
          char city[20];
          unsigned lon zipcode;
          char tel[14];
     }
    如果要給student結(jié)構(gòu)中成員address結(jié)構(gòu)中的zipcode賦值, 則可寫成:
      student.address.zipcode=200001;
    每個結(jié)構(gòu)成員名從最外層直到最內(nèi)層逐個被列出, 即嵌套式結(jié)構(gòu)成員的表達(dá)
方式是:
      結(jié)構(gòu)變量名.嵌套結(jié)構(gòu)變量名.結(jié)構(gòu)成員名
    其中: 嵌套結(jié)構(gòu)可以有很多, 結(jié)構(gòu)成員名為最內(nèi)層結(jié)構(gòu)中不是結(jié)構(gòu)的成員名。

    二、位結(jié)構(gòu)
    位結(jié)構(gòu)是一種特殊的結(jié)構(gòu), 在需按位訪問一個字節(jié)或字的多個位時, 位結(jié)構(gòu)
比按位運(yùn)算符更加方便。
    位結(jié)構(gòu)定義的一般形式為:
     struct位結(jié)構(gòu)名{
          數(shù)據(jù)類型 變量名: 整型常數(shù);
          數(shù)據(jù)類型 變量名: 整型常數(shù);
     } 位結(jié)構(gòu)變量;
    其中: 數(shù)據(jù)類型必須是int(unsigned或signed)。 整型常數(shù)必須是非負(fù)的整
數(shù), 范圍是0~15, 表示二進(jìn)制位的個數(shù), 即表示有多少位。
    變量名是選擇項, 可以不命名, 這樣規(guī)定是為了排列需要。
    例如: 下面定義了一個位結(jié)構(gòu)。
     struct{
          unsigned incon: 8;  /*incon占用低字節(jié)的0~7共8位*/
          unsigned txcolor: 4;/*txcolor占用高字節(jié)的0~3位共4位*/
          unsigned bgcolor: 3;/*bgcolor占用高字節(jié)的4~6位共3位*/
          unsigned blink: 1;  /*blink占用高字節(jié)的第7位*/
     }ch;
    位結(jié)構(gòu)成員的訪問與結(jié)構(gòu)成員的訪問相同。
    例如: 訪問上例位結(jié)構(gòu)中的bgcolor成員可寫成:
      ch.bgcolor

    注意:
    1. 位結(jié)構(gòu)中的成員可以定義為unsigned, 也可定義為signed,  但當(dāng)成員長
度為1時, 會被認(rèn)為是unsigned類型。因為單個位不可能具有符號。
    2. 位結(jié)構(gòu)中的成員不能使用數(shù)組和指針, 但位結(jié)構(gòu)變量可以是數(shù)組和指針,
如果是指針, 其成員訪問方式同結(jié)構(gòu)指針。
    3. 位結(jié)構(gòu)總長度(位數(shù)), 是各個位成員定義的位數(shù)之和,  可以超過兩個字
節(jié)。
    4. 位結(jié)構(gòu)成員可以與其它結(jié)構(gòu)成員一起使用。
    例如:
     struct info{
          char name[8];
          int age;
          struct addr address;
          float pay;
          unsigned state: 1;
          unsigned pay: 1;
          }workers;'
    上例的結(jié)構(gòu)定義了關(guān)于一個工從的信息。其中有兩個位結(jié)構(gòu)成員, 每個位結(jié)
構(gòu)成員只有一位, 因此只占一個字節(jié)但保存了兩個信息, 該字節(jié)中第一位表示工
人的狀態(tài), 第二位表示工資是否已發(fā)放。由此可見使用位結(jié)構(gòu)可以節(jié)省存貯空間。

                    聯(lián)       合(union)
    1. 聯(lián)合說明和聯(lián)合變量定義
    聯(lián)合也是一種新的數(shù)據(jù)類型, 它是一種特殊形式的變量。
    聯(lián)合說明和聯(lián)合變量定義與結(jié)構(gòu)十分相似。其形式為:
     union 聯(lián)合名{
          數(shù)據(jù)類型 成員名;
          數(shù)據(jù)類型 成員名;
          ...
     } 聯(lián)合變量名;
    聯(lián)合表示幾個變量公用一個內(nèi)存位置, 在不同的時間保存不同的數(shù)據(jù)類型
和不同長度的變量。
    下例表示說明一個聯(lián)合a_bc:
     union a_bc{
          int i;
          char mm;
     };
    再用已說明的聯(lián)合可定義聯(lián)合變量。
    例如用上面說明的聯(lián)合定義一個名為lgc的聯(lián)合變量, 可寫成:
      union a_bc lgc;
    在聯(lián)合變量lgc中, 整型量i和字符mm公用同一內(nèi)存位置。
    當(dāng)一個聯(lián)合被說明時, 編譯程序自動地產(chǎn)生一個變量, 其長度為聯(lián)合中最大
的變量長度。
    聯(lián)合訪問其成員的方法與結(jié)構(gòu)相同。同樣聯(lián)合變量也可以定義成數(shù)組或指針,
但定義為指針時, 也要用"->"符號, 此時聯(lián)合訪問成員可表示成:
     聯(lián)合名->成員名
    另外, 聯(lián)合既可以出現(xiàn)在結(jié)構(gòu)內(nèi), 它的成員也可以是結(jié)構(gòu)。
    例如:
     struct{
          int age;
          char *addr;
          union{
               int i;
               char *ch;
          }x;
     }y[10];
    若要訪問結(jié)構(gòu)變量y[1]中聯(lián)合x的成員i, 可以寫成:
      y[1].x.i;
    若要訪問結(jié)構(gòu)變量y[2]中聯(lián)合x的字符串指針ch的第一個字符可寫成:
      *y[2].x.ch;
    若寫成"y[2].x.*ch;"是錯誤的。

    2. 結(jié)構(gòu)和聯(lián)合的區(qū)別
    結(jié)構(gòu)和聯(lián)合有下列區(qū)別:
    1. 結(jié)構(gòu)和聯(lián)合都是由多個不同的數(shù)據(jù)類型成員組成, 但在任何同一時刻,
聯(lián)合中只存放了一個被選中的成員, 而結(jié)構(gòu)的所有成員都存在。
    2. 對于聯(lián)合的不同成員賦值, 將會對其它成員重寫,  原來成員的值就不存
在了, 而對于結(jié)構(gòu)的不同成員賦值是互不影響的。
    下面舉一個例了來加對深聯(lián)合的理解。
    例4:
     main()
     {
          union{                   /*定義一個聯(lián)合*/
               int i;
               struct{             /*在聯(lián)合中定義一個結(jié)構(gòu)*/
                    char first;
                    char second;
               }half;
          }number;
          number.i=0x4241;         /*聯(lián)合成員賦值*/
          printf("%c%c\n", number.half.first, mumber.half.second);
          number.half.first='a';   /*聯(lián)合中結(jié)構(gòu)成員賦值*/
          number.half.second='b';
          printf("%x\n", number.i);
          getch();
     }
    輸出結(jié)果為:
     AB
     6261
    從上例結(jié)果可以看出: 當(dāng)給i賦值后, 其低八位也就是first和second的值;
當(dāng)給first和second賦字符后, 這兩個字符的ASCII碼也將作為i 的低八位和高八
位。


                    枚       舉(enum)

    枚舉是一個被命名的整型常數(shù)的集合, 枚舉在日常生活中很常見。
    例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY, 就是一個枚舉。
    枚舉的說明與結(jié)構(gòu)和聯(lián)合相似, 其形式為:
          enum 枚舉名{
               標(biāo)識符[=整型常數(shù)],
               標(biāo)識符[=整型常數(shù)],
               ...
               標(biāo)識符[=整型常數(shù)],
          } 枚舉變量;
    如果枚舉沒有初始化, 即省掉"=整型常數(shù)"時, 則從第一個標(biāo)識符開始,  順
次賦給標(biāo)識符0, 1, 2, ...。但當(dāng)枚舉中的某個成員賦值后, 其后的成員按依次
加1的規(guī)則確定其值。
    例如下列枚舉說明后, x1, x2, x3, x4的值分別為0, 1, 2, 3。
     enum string{x1, x2, x3, x4}x;
    當(dāng)定義改變成:
      enum string
      {
          x1,
          x2=0,
          x3=50,
          x4,
      }x;
    則x1=0, x2=0, x3=50, x4=51
    注意:
    1. 枚舉中每個成員(標(biāo)識符)結(jié)束符是",",  不是";", 最后一個成員可省略
","。
    2. 初始化時可以賦負(fù)數(shù), 以后的標(biāo)識符仍依次加1。
    3. 枚舉變量只能取枚舉說明結(jié)構(gòu)中的某個標(biāo)識符常量。
    例如:
      enum string
      {
          x1=5,
          x2,
          x3,
          x4,
      };
     enum strig x=x3;
    此時, 枚舉變量x實(shí)際上是7。



                    類   型   說   明

    類型說明的格式為:
     typedef 類型 定義名;
    類型說明只定義了一個數(shù)據(jù)類型的新名字而不是定義一種新的數(shù)據(jù)類型。這
里類型是Turbo C許可的任何一種數(shù)據(jù)類型。定義名表示這個類型的新名字。
    例如: 用下面語句定義整型數(shù)的新名字:
     typedef int SIGNED_INT;
    使用說明后, SIGNED_INT就成為int的同義詞了, 此時可以用SIGNED_INT 定
義整型變量。
    例如:  SIGNED_INT i, j;(與int i, j等效)。
    但 long SIGNED_INT i, j; 是非法的。
    typedef同樣可用來說明結(jié)構(gòu)、聯(lián)合以及枚舉。
    說明一個結(jié)構(gòu)的格式為:
      typedef struct{
          數(shù)據(jù)類型  成員名;
          數(shù)據(jù)類型  成員名;
          ...
        } 結(jié)構(gòu)名;
    此時可直接用結(jié)構(gòu)名定義結(jié)構(gòu)變量了。例如:
     typedef struct{
          char name[8];
          int class;
          char subclass[6];
          float math, phys, chem, engl, biol;
      } student;
      student Liuqi;
    則Liuqi被定義為結(jié)構(gòu)數(shù)組和結(jié)構(gòu)指針。
    在第二節(jié)講過的文件操作中, 用到的FILE就是一個已被說明的結(jié)構(gòu), 其說明
如下:
     typedef struct
     {
          short level;
          unsigned flags;
          char fd;
          unsigned char hold;
          short bsize;
          unsigned char *buffer;
          unsigned char *curp;
          unsigned istemp;
          short token;
     } FILE
    這個結(jié)構(gòu)說明已包含在stdio.h中, 用戶只要直接用FILE 定義文件指針變量
就可以。事實(shí)上, 引入類型說明的目的并非為了方便, 而是為了便于程序的移植。



                預(yù)  處  理  指  令

    由ANSI的標(biāo)準(zhǔn)規(guī)定, 預(yù)處理指令主要包括:
     #define
     #error
     #if
     #else
     #elif
     #endif
     #ifdef
     #ifndef
     #undef
     #line
     #pragma
    由上述指令可以看出, 每個預(yù)處理指令均帶有符號"#"。下面只介紹一些常
用指令。
    1. #define 指令
    #define指令是一個宏定義指令, 定義的一般形式是:
     #define 宏替換名字符串(或數(shù)值)
    由#define指令定義后,  在程序中每次遇到該宏替換名時就用所定義的字符
串(或數(shù)值)代替它。
    例如: 可用下面語句定義TRUE表示數(shù)值1, FALSE表示0。
     #define TRUE 1
     #define FALSE 0
    一旦在源程序中使用了TRUE和FALSE, 編譯時會自動的用1和0代替。
    注意:
    1. 在宏定義語名后沒有";"
    2. 在Turbo C程序中習(xí)慣上用大寫字符作為宏替換名, 而且常放在程序開頭。
    3. 宏定義還有一個特點(diǎn), 就是宏替換名可以帶有形式參數(shù),  在程序中用到
時, 實(shí)際參數(shù)會代替這些形式參數(shù)。
    例如:
     #define MAX(x, y) (x>y)?x:y
     main()
     {
          int i=10, j=15;
          printf("The Maxmum is %d", MAX(i, j);
     }
    上例宏定義語句的含義是用宏替換名MAX(x, y)代替x, y中較大者,  同樣也
可定義:
     #define MIN(x, y) (x
    程序也允許嵌入其它文件, 例如:
     main()
     {
          #include
     }
    其中help.c為另一個文件, 內(nèi)容可為
       printf("Glad to meet you here!");
    上例編譯時將按集成開發(fā)環(huán)境的Options/Directories/Include directories
中指定的包含文件路徑查找被嵌入文件。

    4. #if、#else、#endif指令
    #if、#els和#endif指令為條件編擇指令, 它的一般形式為:
     #if 常數(shù)表達(dá)式
          語句段;
     #else
          語句段;
     #endif
    上述結(jié)構(gòu)的含義是: 若#if指令后的常數(shù)表達(dá)式為真, 則編譯#if到#else 之
間的程序段; 否則編譯#else到#endif之間的程序段。
    例如:
     #define MAX 200
     main()
     {
          #if MAX>999
               printf("compiled for bigger\n");
          #else
               printf("compiled for small\n");
          #endif
     }

    5. #undef指令
    #undef指令用來刪除事先定義的宏定義, 其一般形式為:
     #undef 宏替換名
    例如:
      #define TRUE 1
       ...
      #undef TURE
    #undef主要用來使宏替換名只限定在需要使用它們的程序段中。

文章錄入:蕭雨    責(zé)任編輯:admin  
 版權(quán)聲明
   如果本網(wǎng)站所轉(zhuǎn)載內(nèi)容不慎侵犯了您的權(quán)益,請與我們聯(lián)系,我們將會及時處理。如轉(zhuǎn)載本網(wǎng)內(nèi)容,請注明出處。
 發(fā)表評論
關(guān)于本站 網(wǎng)站聲明 廣告服務(wù)  聯(lián)系方式  付款方式  站內(nèi)導(dǎo)航  客服中心  友情鏈接   
Copyright © 2004-2006 考試吧 (Exam8.com) All Rights Reserved 
中國科學(xué)院研究生院中關(guān)村園區(qū)(北京市海淀區(qū))