欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          C語言基礎(chǔ)教程(四)指針、結(jié)構(gòu)、聯(lián)合和枚舉

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

          1、 指         針(point)

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

              1. 指針和地址
              1.1 指針基本概念及其指針變量的定義
              1.1.1 指針變量的定義
              我們知道變量在計算機內(nèi)是占有一塊存貯區(qū)域的, 變量的值就存放在這塊區(qū)
          域之中, 在計算機內(nèi)部, 通過訪問或修改這塊區(qū)域的內(nèi)容來訪問或修改相應(yīng)的變
          量。Turbo C語言中, 對于變量的訪問形式之一, 就是先求出變量的地址,  然后
          再通過地址對它進行訪問, 這就是這里所要論述的指針及其指針變量。
              所謂變量的指針, 實際上指變量的地址。變量的地址雖然在形式上好象類似
          于整數(shù), 但在概念上不同于以前介紹過的整數(shù), 它屬于一種新的數(shù)據(jù)類型, 即指
          針類型。Turbo C中, 一般用”指針”來指明這樣一個表達式&x的類型,  而用 “地
          址”作為它的值, 也就是說, 若x為一整型變量, 則表達式&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;
          運算符*訪問以ip為地址的存貯區(qū)域, 而ip中存放的是變量i的地址, 因此, *ip
          訪問的是地址為1800的存貯區(qū)域(因為是整數(shù), 實際上是從1800開始的兩個字節(jié)),
          它就是i所占用的存貯區(qū)域, 所以上面的賦值表達式等價于
               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. 賦值運算結(jié)果
          這時賦值表達式:
               p2=p1
          就使p2與p1指向同一對象i, 此時*p2就等價于i, 而不是j, 圖2.就變成圖3.所示:
                      p1               i
                  ┏━━━┓       ┏━━━┓
                  ┃      ╂──→ ┃ ‘a’  ┃
                  ┗━━━┛  ┌→ ┗━━━┛
                      p2      │       j
                  ┏━━━┓  │   ┏━━━┓
                  ┃      ╂─┘   ┃ ‘b’  ┃
                  ┗━━━┛       ┗━━━┛
                      圖3. p2=p1時的情形
          如果執(zhí)行如下表達式:
               *p2=*p1;
          則表示把p1指向的內(nèi)容賦給p2所指的區(qū)域, 此時圖2.就變成圖4.所示
                      p1               i
                  ┏━━━┓       ┏━━━┓
                  ┃      ╂──→ ┃ ‘a’  ┃
                  ┗━━━┛       ┗━━━┛
                      p2               j
                  ┏━━━┓       ┏━━━┓
                  ┃      ╂──→ ┃ ‘a’  ┃
                  ┗━━━┛       ┗━━━┛
                      圖4. *p2=*p1時的情形
              通過指針訪問它所指向的一個變量是以間接訪問的形式進行的, 所以比直接
          訪問一個變量要費時間, 而且不直觀, 因為通過指針要訪問哪一個變量, 取決于
          指針的值(即指向), 例如”*p2=*p1;”實際上就是”j=i;”, 前者不僅速度慢而且目
          的不明。但由于指針是變量, 我們可以通過改變它們的指向, 以間接訪問不同的
          變量, 這給程序員帶來靈活性, 也使程序代碼編寫得更為簡潔和有效。
              指針變量可出現(xiàn)在表達式中, 設(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. 地址運算
              指針允許的運算方式有:
              (1). 指針在一定條件下, 可進行比較, 這里所說的一定條件,  是指兩個指
          針指向同一個對象才有意義, 例如兩個指針變量p, q指向同一數(shù)組, 則<, >, >=,
          <=, ==等關(guān)系運算符都能正常進行。若p==q為真, 則表示p, q指向數(shù)組的同一元
          素; 若p<q為真, 則表示p所指向的數(shù)組元素在q所指向的數(shù)組元素之前(對于指向
          數(shù)組元素的指針在下面將作詳細(xì)討論)。
              (2). 指針和整數(shù)可進行加、減運算。設(shè)p是指向某一數(shù)組元素的指針, 開始
          時指向數(shù)組的第0號元素, 設(shè)n為一整數(shù), 則
               p+n
          就表示指向數(shù)組的第n號元素(下標(biāo)為n的元素)。
              不論指針變量指向何種數(shù)據(jù)類型, 指針和整數(shù)進行加、減運算時, 編譯程序
          總根據(jù)所指對象的數(shù)據(jù)長度對n放大, 在一般微機上, char放大因子為1, int、
          short放大因子為2, long和float放大因子為4, double放大因子為8。 對于下面
          講述到的結(jié)構(gòu)或聯(lián)合, 也仍然遵守這一原則。
              (3). 兩個指針變量在一定條件下, 可進行減法運算。設(shè)p, q指向同一數(shù)組,
          則p-q的絕對值表示p所指對象與q所指對象之間的元素個數(shù)。 其相減的結(jié)果遵守
          對象類型的字節(jié)長度進行縮小的規(guī)則。

              2. 指針和數(shù)組
              指針和數(shù)組有著密切的關(guān)系, 任何能由數(shù)組下標(biāo)完成的操作也都可用指針來
          實現(xiàn), 但程序中使用指針可使代碼更緊湊、更靈活。

              2.1. 指向數(shù)組元素的指針
              我們定義一個整型數(shù)組和一個指向整型的指針變量:
                    int a[10], *p;
          和前面介紹過的方法相同, 可以使整型指針p指向數(shù)組中任何一個元素,  假定給
          出賦值運算
                    p=&a[0];
          此時, p指向數(shù)組中的第0號元素, 即a[0], 指針變量p中包含了數(shù)組元素a[0] 的
          地址, 由于數(shù)組元素在內(nèi)存中是連續(xù)存放的, 因此,  我們就可以通過指針變量p
          及其有關(guān)運算間接訪問數(shù)組中的任何一個元素。
              Turbo C中, 數(shù)組名是數(shù)組的第0號元素的地址, 因此下面兩個語句是等價的
               p=&a[0];
               p=a;
          根據(jù)地址運算規(guī)則, a+1為a[1]的地址, a+i就為a[i]的地址。
              下面我們用指針給出數(shù)組元素的地址和內(nèi)容的幾種表示形式。
              (1). p+i和a+i均表示a[i]的地址, 或者講, 它們均指向數(shù)組第i號元素, 即
          指向a[i]。
              (2). *(p+i)和*(a+i)都表示p+i和a+i所指對象的內(nèi)容, 即為a[i]。
              (3). 指向數(shù)組元素的指針, 也可以表示成數(shù)組的形式, 也就是說,  它允許
          指針變量帶下標(biāo), 如p[i]與*(p+i)等價。
              假若:      p=a+5;
          則p[2]就相當(dāng)于*(p+2), 由于p指向a[5], 所以p[2]就相當(dāng)于a[7]。而p[-3]就相
          當(dāng)于*(p-3), 它表示a[2]。

              2.2. 指向二維數(shù)組的指針
              2.2.1. 二維數(shù)組元素的地址
              為了說明問題, 我們定義以下二維數(shù)組:
               int a[3][4]={{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
          a為二維數(shù)組名, 此數(shù)組有3行4列, 共12個元素。但也可這樣來理解, 數(shù)組a由三
          個元素組成: a[0], a[1], a[2]。而它勻中每個元素又是一個一維數(shù)組, 且都含
          有4個元素 (相當(dāng)于4列),  例如, a[0]所代表的一維數(shù)組所包含的 4 個元素為
          a[0][0], a[0][1], a[0][2], a[0][3]。如圖5.所示:
                  ┏━━━━┓    ┏━┳━┳━┳━┓
            a─→ ┃  a[0]  ┃─→┃0 ┃1 ┃2 ┃3 ┃
                  ┣━━━━┫    ┣━╋━╋━╋━┫
                  ┃  a[1]  ┃─→┃4 ┃5 ┃6 ┃7 ┃
                  ┣━━━━┫    ┣━╋━╋━╋━┫
                  ┃  a[2]  ┃─→┃8 ┃9 ┃10┃11┃
                  ┗━━━━┛    ┗━┻━┻━┻━┛
                              圖5.
              但從二維數(shù)組的角度來看, a代表二維數(shù)組的首地址,  當(dāng)然也可看成是二維
          數(shù)組第0行的首地址。a+1就代表第1行的首地址, a+2就代表第2行的首地址。如
          果此二維數(shù)組的首地址為1000, 由于第0行有4個整型元素, 所以a+1為1008, a+2
          也就為1016。如圖6.所示
                                      a[3][4]
                             a    ┏━┳━┳━┳━┓
                        (1000)─→┃0 ┃1 ┃2 ┃3 ┃
                             a+1  ┣━╋━╋━╋━┫
                        (1008)─→┃4 ┃5 ┃6 ┃7 ┃
                             a+2  ┣━╋━╋━╋━┫
                        (1016)─→┃8 ┃9 ┃10┃11┃
                                  ┗━┻━┻━┻━┛
                                        圖6.
              既然我們把a[0], a[1], a[2]看成是一維數(shù)組名, 可以認(rèn)為它們分別代表它
          們所對應(yīng)的數(shù)組的首地址, 也就是講,  a[0]代表第 0 行中第 0 列元素的地址,
          即&a[0][0], a[1]是第1行中第0列元素的地址, 即&a[1][0], 根據(jù)地址運算規(guī)則,
          a[0]+1即代表第0行第1列元素的地址, 即&a[0][1], 一般而言, a[i]+j即代表第
          i行第j列元素的地址, 即&a[i][j]。
              另外, 在二維數(shù)組中, 我們還可用指針的形式來表示各元素的地址。如前所
          述, a[0]與*(a+0)等價, a[1]與*(a+1)等價, 因此a[i]+j就與*(a+i)+j等價, 它
          表示數(shù)組元素a[i][j]的地址。
              因此, 二維數(shù)組元素a[i][j]可表示成*(a[i]+j)或*(*(a+i)+j),  它們都與
          a[i][j]等價, 或者還可寫成(*(a+i))[j]。
              另外, 要補充說明一下, 如果你編寫一個程序輸出打印a和*a,  你可發(fā)現(xiàn)它
          們的值是相同的, 這是為什么呢? 我們可這樣來理解: 首先, 為了說明問題, 我
          們把二維數(shù)組人為地看成由三個數(shù)組元素a[0], a[1], a[2]組成, 將a[0], a[1],
          a[2]看成是數(shù)組名它們又分別是由4個元素組成的一維數(shù)組。因此, a表示數(shù)組第
          0行的地址, 而*a即為a[0], 它是數(shù)組名, 當(dāng)然還是地址, 它就是數(shù)組第0 行第0
          列元素的地址。

              2.2.2 指向一個由n個元素所組成的數(shù)組指針
              在Turbo C中, 可定義如下的指針變量:
                int (*p)[3];
              指針p為指向一個由3個元素所組成的整型數(shù)組指針。在定義中, 圓括號是不
          能少的, 否則它是指針數(shù)組, 這將在后面介紹。這種數(shù)組的指針不同于前面介紹
          的整型指針, 當(dāng)整型指針指向一個整型數(shù)組的元素時, 進行指針(地址)加1運算,
          表示指向數(shù)組的下一個元素, 此時地址值增加了2(因為放大因子為2), 而如上所
          定義的指向一個由3個元素組成的數(shù)組指針, 進行地址加1運算時, 其地址值增加
          了6(放大因子為2×3=6), 這種數(shù)組指針在Turbo C中用得較少,  但在處理二維數(shù)
          組時, 還是很方便的。例如:
                    int a[3][4], (*p)[4];
                    p=a;
              開始時p指向二維數(shù)組第0行, 當(dāng)進行p+1運算時, 根據(jù)地址運算規(guī)則,  此時
          放大因子為4×2=8, 所以此時正好指向二維數(shù)組的第1行。和二維數(shù)組元素地址計
          算的規(guī)則一樣, *p+1指向a[0][1], *(p+i)+j則指向數(shù)組元素a[i][j]。
               例1
               int a[3] [4]={
               {1,3,5,7},
               {9,11,13,15},
               {17,19,21,23}
              };
              main()
              {
                   int i,(*b)[4];
                     b=a+1;                  /* b指向二維數(shù)組的第1行, 此時*b[0]或
                                               **b是a[1][0] */
                   for(i=1;i<=4;b=b[0]+2,i++)/* 修改b的指向, 每次增加2 */
                     printf(“%dt”,*b[0]);
                   printf(“n”);
                   for (i=0; i<2; i++) {
                     b=a+i;                  /* 修改b的指向,  每次跳過二維數(shù)組的
                                                一行 */
                     printf(“%dt”,*(b[i]+1));
                  }
                   printf (“n”);
               }
              程序運行結(jié)果如下:
               9    13   17   21
               3    11   19

              3. 字符指針
              我們已經(jīng)知道, 字符串常量是由雙引號括起來的字符序列, 例如:
                    “a string”
          就是一個字符串常量, 該字符串中因為字符a后面還有一個空格字符, 所以它由8
          個字符序列組成。在程序中如出現(xiàn)字符串常量C 編譯程序就給字符串常量按排一
          存貯區(qū)域, 這個區(qū)域是靜態(tài)的, 在整個程序運行的過程中始終占用, 平時所講的
          字符串常量的長度是指該字符串的字符個數(shù), 但在按排存貯區(qū)域時, C 編譯程序
          還自動給該字符串序列的末尾加上一個空字符’