久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網
      最全最豐富的資訊網站

      《C語言完全教程》第七章 指針

      第七章 指針

      指針簡介

        指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運用指針編程是C語言最主要的風格之一。利用指針變量可以表示各種數(shù)據(jù)結構; 能很方便地使用數(shù)組和字符串; 并能象匯編語言一樣處理內存地址,從而編出精練而高效的程序。指針極大地豐富了C語言的功能。 學習指針是學習C語言中最重要的一環(huán), 能否正確理解和使用指針是我們是否掌握C語言的一個標志。同時, 指針也是C語言中最為困難的一部分,在學習中除了要正確理解基本概念,還必須要多編程,上機調試。只要作到這些,指針也是不難掌握的。

        指針的基本概念 在計算機中,所有的數(shù)據(jù)都是存放在存儲器中的。 一般把存儲器中的一個字節(jié)稱為一個內存單元, 不同的數(shù)據(jù)類型所占用的內存單元數(shù)不等,如整型量占2個單元,字符量占1個單元等, 在第二章中已有詳細的介紹。為了正確地訪問這些內存單元, 必須為每個內存單元編上號。 根據(jù)一個內存單元的編號即可準確地找到該內存單元。內存單元的編號也叫做地址。 既然根據(jù)內存單元的編號或地址就可以找到所需的內存單元,所以通常也把這個地址稱為指針。 內存單元的指針和內存單元的內容是兩個不同的概念。 可以用一個通俗的例子來說明它們之間的關系。我們到銀行去存取款時, 銀行工作人員將根據(jù)我們的帳號去找我們的存款單, 找到之后在存單上寫入存款、取款的金額。在這里,帳號就是存單的指針, 存款數(shù)是存單的內容。對于一個內存單元來說,單元的地址即為指針, 其中存放的數(shù)據(jù)才是該單元的內容。在C語言中, 允許用一個變量來存放指針,這種變量稱為指針變量。因此, 一個指針變量的值就是某個內存單元的地址或稱為某內存單元的指針。圖中,設有字符變量C,其內容為“K”(ASCII碼為十進制數(shù) 75),C占用了011A號單元(地址用十六進數(shù)表示)。設有指針變量P,內容為011A, 這種情況我們稱為P指向變量C,或說P是指向變量C的指針。 嚴格地說,一個指針是一個地址, 是一個常量。而一個指針變量卻可以被賦予不同的指針值,是變。 但在常把指針變量簡稱為指針。為了避免混淆,我們中約定:“指針”是指地址, 是常量,“指針變量”是指取值為地址的變量。 定義指針的目的是為了通過指針去訪問內存單元。
       
         既然指針變量的值是一個地址, 那么這個地址不僅可以是變量的地址, 也可以是其它數(shù)據(jù)結構的地址。在一個指針變量中存放一
      個數(shù)組或一個函數(shù)的首地址有何意義呢? 因為數(shù)組或函數(shù)都是連續(xù)存放的。通過訪問指針變量取得了數(shù)組或函數(shù)的首地址, 也就找到了該數(shù)組或函數(shù)。這樣一來, 凡是出現(xiàn)數(shù)組,函數(shù)的地方都可以用一個指針變量來表示, 只要該指針變量中賦予數(shù)組或函數(shù)的首地址即可。這樣做, 將會使程序的概念十分清楚,程序本身也精練,高效。在C語言中, 一種數(shù)據(jù)類型或數(shù)據(jù)結構往往都占有一組連續(xù)的內存單元。 用“地址”這個概念并不能很好地描述一種數(shù)據(jù)類型或數(shù)據(jù)結構, 而“指針”雖然實際上也是一個地址,但它卻是一個數(shù)據(jù)結構的首地址, 它是“指向”一個數(shù)據(jù)結構的,因而概念更為清楚,表示更為明確。 這也是引入“指針”概念的一個重要原因。

      指針變量的類型說明

        對指針變量的類型說明包括三個內容:
      (1)指針類型說明,即定義變量為一個指針變量;
      (2)指針變量名;
      (3)變量值(指針)所指向的變量的數(shù)據(jù)類型。
         其一般形式為: 類型說明符 *變量名;
         其中,*表示這是一個指針變量,變量名即為定義的指針變量名,類型說明符表示本指針變量所指向的變量的數(shù)據(jù)類型。
         例如: int *p1;表示p1是一個指針變量,它的值是某個整型變量的地址。 或者說p1指向一個整型變量。至于p1究竟指向哪一個整型變量, 應由向p1賦予的地址來決定。
         再如:
      staic int *p2; /*p2是指向靜態(tài)整型變量的指針變量*/
      float *p3; /*p3是指向浮點變量的指針變量*/
      char *p4; /*p4是指向字符變量的指針變量*/ 應該注意的是,一個指針變量只能指向同類型的變量,如P3 只能指向浮點變量,不能時而指向一個浮點變量, 時而又指向一個字符變量。

      指針變量的賦值

        指針變量同普通變量一樣,使用之前不僅要定義說明, 而且必須賦予具體的值。未經賦值的指針變量不能使用, 否則將造成系統(tǒng)混亂,甚至死機。指針變量的賦值只能賦予地址, 決不能賦予任何其它數(shù)據(jù),否則將引起錯誤。在C語言中, 變量的地址是由編譯系統(tǒng)分配的,對用戶完全透明,用戶不知道變量的具體地址。 C語言中提供了地址運算符&來表示變量的地址。其一般形式為: & 變量名; 如&a變示變量a的地址,&b表示變量b的地址。 變量本身必須預先說明。設有指向整型變量的指針變量p,如要把整型變量a 的地址賦予p可以有以下兩種方式:
      (1)指針變量初始化的方法 int a;
      int *p=&a;
      (2)賦值語句的方法 int a;
      int *p;
      p=&a;
      不允許把一個數(shù)賦予指針變量,故下面的賦值是錯誤的: int *p;p=1000; 被賦值的指針變量前不能再加“*”說明符,如寫為*p=&a 也是錯誤的

      指針變量的運算

        指針變量可以進行某些運算,但其運算的種類是有限的。 它只能進行賦值運算和部分算術運算及關系運算。
      1.指針運算符

      (1)取地址運算符&
         取地址運算符&是單目運算符,其結合性為自右至左,其功能是取變量的地址。在scanf函數(shù)及前面介紹指針變量賦值中,我們已經了解并使用了&運算符。

      (2)取內容運算符*
         取內容運算符*是單目運算符,其結合性為自右至左,用來表示指針變量所指的變量。在*運算符之后跟的變量必須是指針變量。需要注意的是指針運算符*和指針變量說明中的指針說明符* 不是一回事。在指針變量說明中,“*”是類型說明符,表示其后的變量是指針類型。而表達式中出現(xiàn)的“*”則是一個運算符用以表示指針變量所指的變量。
      main(){
      int a=5,*p=&a;
      printf (“%d”,*p);
      }
      ……
      表示指針變量p取得了整型變量a的地址。本語句表示輸出變量a的值。

      2.指針變量的運算

      (1)賦值運算

      指針變量的賦值運算有以下幾種形式:
      ①指針變量初始化賦值,前面已作介紹。

      ②把一個變量的地址賦予指向相同數(shù)據(jù)類型的指針變量。例如:
      int a,*pa;
      pa=&a; /*把整型變量a的地址賦予整型指針變量pa*/

      ③把一個指針變量的值賦予指向相同類型變量的另一個指針變量。如:
      int a,*pa=&a,*pb;
      pb=pa; /*把a的地址賦予指針變量pb*/
      由于pa,pb均為指向整型變量的指針變量,因此可以相互賦值。 ④把數(shù)組的首地址賦予指向數(shù)組的指針變量。
      例如: int a[5],*pa;
      pa=a; (數(shù)組名表示數(shù)組的首地址,故可賦予指向數(shù)組的指針變量pa)
      也可寫為:
      pa=&a[0]; /*數(shù)組第一個元素的地址也是整個數(shù)組的首地址,
      也可賦予pa*/
      當然也可采取初始化賦值的方法:
      int a[5],*pa=a;

      ⑤把字符串的首地址賦予指向字符類型的指針變量。例如: char *pc;pc=”c language”;或用初始化賦值的方法寫為: char *pc=”C Language”; 這里應說明的是并不是把整個字符串裝入指針變量, 而是把存放該字符串的字符數(shù)組的首地址裝入指針變量。 在后面還將詳細介紹。

      ⑥把函數(shù)的入口地址賦予指向函數(shù)的指針變量。例如: int (*pf)();pf=f; /*f為函數(shù)名*/

      (2)加減算術運算

        對于指向數(shù)組的指針變量,可以加上或減去一個整數(shù)n。設pa是指向數(shù)組a的指針變量,則pa+n,pa-n,pa++,++pa,pa–,–pa 運算都是合法的。指針變量加或減一個整數(shù)n的意義是把指針指向的當前位置(指向某數(shù)組元素)向前或向后移動n個位置。應該注意,數(shù)組指針變量向前或向后移動一個位置和地址加1或減1 在概念上是不同的。因為數(shù)組可以有不同的類型, 各種類型的數(shù)組元素所占的字節(jié)長度是不同的。如指針變量加1,即向后移動1 個位置表示指針變量指向下一個數(shù)據(jù)元素的首地址。而不是在原地址基礎上加1。
      例如:
      int a[5],*pa;
      pa=a; /*pa指向數(shù)組a,也是指向a[0]*/
      pa=pa+2; /*pa指向a[2],即pa的值為&pa[2]*/ 指針變量的加減運算只能對數(shù)組指針變量進行, 對指向其它類型變量的指針變量作加減運算是毫無意義的。(3)兩個指針變量之間的運算只有指向同一數(shù)組的兩個指針變量之間才能進行運算, 否則運算毫無意義。

      ①兩指針變量相減
      兩指針變量相減所得之差是兩個指針所指數(shù)組元素之間相差的元素個數(shù)。實際上是兩個指針值(地址) 相減之差再除以該數(shù)組元素的長度(字節(jié)數(shù))。例如pf1和pf2 是指向同一浮點數(shù)組的兩個指針變量,設pf1的值為2010H,pf2的值為2000H,而浮點數(shù)組每個元素占4個字節(jié),所以pf1-pf2的結果為(2000H-2010H)/4=4,表示pf1和 pf2之間相差4個元素。兩個指針變量不能進行加法運算。 例如, pf1+pf2是什么意思呢?毫無實際意義。

      ②兩指針變量進行關系運算
      指向同一數(shù)組的兩指針變量進行關系運算可表示它們所指數(shù)組元素之間的關系。例如:
      pf1==pf2表示pf1和pf2指向同一數(shù)組元素
      pf1>pf2表示pf1處于高地址位置
      pf1<pf2表示pf2處于低地址位置
      main(){
      int a=10,b=20,s,t,*pa,*pb;
      pa=&a;
      pb=&b;
      s=*pa+*pb;
      t=*pa**pb;
      printf(“a=%dnb=%dna+b=%dna*b=%dn”,a,b,a+b,a*b);
      printf(“s=%dnt=%dn”,s,t);
      }
      ……
      說明pa,pb為整型指針變量
      給指針變量pa賦值,pa指向變量a。
      給指針變量pb賦值,pb指向變量b。
      本行的意義是求a+b之和,(*pa就是a,*pb就是b)。
      本行是求a*b之積。
      輸出結果。
      輸出結果。
      ……
      指針變量還可以與0比較。設p為指針變量,則p==0表明p是空指針,它不指向任何變量;p!=0表示p不是空指針。空指針是由對指針變量賦予0值而得到的。例如: #define NULL 0 int *p=NULL; 對指針變量賦0值和不賦值是不同的。指針變量未賦值時,可以是任意值,是不能使用的。否則將造成意外錯誤。而指針變量賦0值后,則可以使用,只是它不指向具體的變量而已。
      main(){
      int a,b,c,*pmax,*pmin;
      printf(“input three numbers:n”);
      scanf(“%d%d%d”,&a,&b,&c);
      if(a>b){
      pmax=&a;
      pmin=&b;}
      else{
      pmax=&b;
      pmin=&a;}
      if(c>*pmax) pmax=&c;
      if(c<*pmin) pmin=&c;
      printf(“max=%dnmin=%dn”,*pmax,*pmin);
      }
      ……
      pmax,pmin為整型指針變量。
      輸入提示。
      輸入三個數(shù)字。
      如果第一個數(shù)字大于第二個數(shù)字...
      指針變量賦值
      指針變量賦值

      指針變量賦值
      指針變量賦值
      判斷并賦值
      判斷并賦值
      輸出結果
      ……

      數(shù)組指針變量的說明和使用

        指向數(shù)組的指針變量稱為數(shù)組指針變量。 在討論數(shù)組指針變量的說明和使用之前,我們先明確幾個關系。
      一個數(shù)組是由連續(xù)的一塊內存單元組成的。 數(shù)組名就是這塊連續(xù)內存單元的首地址。一個數(shù)組也是由各個數(shù)組元素(下標變量) 組成的。每個數(shù)組元素按其類型不同占有幾個連續(xù)的內存單元。 一個數(shù)組元素的首地址也是指它所占有的幾個內存單元的首地址。 一個指針變量既可以指向一個數(shù)組,也可以指向一個數(shù)組元素, 可把數(shù)組名或第一個元素的地址賦予它。如要使指針變量指向第i號元素可以把i元素的首地址賦予它或把數(shù)組名加i賦予它。

        設有實數(shù)組a,指向a的指針變量為pa,從圖6.3中我們可以看出有以下關系:
      pa,a,&a[0]均指向同一單元,它們是數(shù)組a的首地址,也是0 號元素a[0]的首地址。pa+1,a+1,&a[1]均指向1號元素a[1]。類推可知a+i,a+i,&a[i]
      指向i號元素a[i]。應該說明的是pa是變量,而a,&a[i]都是常量。在編程時應予以注意。
      main(){
      int a[5],i;
      for(i=0;i<5;i++){
      a[i]=i;
      printf(“a[%d]=%dn”,i,a[i]);
      }
      printf(“n”);
      }
      主函數(shù)
      定義一個整型數(shù)組和一個整型變量
      循環(huán)語句
      給數(shù)組賦值
      打印每一個數(shù)組的值
      ……
      輸出換行
      ……
      數(shù)組指針變量說明的一般形式為:
      類型說明符 * 指針變量名
         其中類型說明符表示所指數(shù)組的類型。 從一般形式可以看出指向數(shù)組的指針變量和指向普通變量的指針變量的說明是相同的。
      引入指針變量后,就可以用兩種方法來訪問數(shù)組元素了。
         第一種方法為下標法,即用a[i]形式訪問數(shù)組元素。 在第四章中介紹數(shù)組時都是采用這種方法。
         第二種方法為指針法,即采用*(pa+i)形式,用間接訪問的方法來訪問數(shù)組元素。
      main(){
      int a[5],i,*pa;
      pa=a;
      for(i=0;i<5;i++){
      *pa=i;
      pa++;
      }
      pa=a;
      for(i=0;i<5;i++){
      printf(“a[%d]=%dn”,i,*pa);
      pa++;
      }
      }
      主函數(shù)
      定義整型數(shù)組和指針
      將指針pa指向數(shù)組a
      循環(huán)
      將變量i的值賦給由指針pa指向的a[]的數(shù)組單元
      將指針pa指向a[]的下一個單元
      ……
      指針pa重新取得數(shù)組a的首地址
      循環(huán)
      用數(shù)組方式輸出數(shù)組a中的所有元素
      將指針pa指向a[]的下一個單元
      ……
      ……
      下面,另舉一例,該例與上例本意相同,但是實現(xiàn)方式不同。
      main(){
      int a[5],i,*pa=a;
      for(i=0;i<5;){
      *pa=i;
      printf(“a[%d]=%dn”,i++,*pa++);
      }
      }
      主函數(shù)
      定義整型數(shù)組和指針,并使指針指向數(shù)組a
      循環(huán)
      將變量i的值賦給由指針pa指向的a[]的數(shù)組單元
      用指針輸出數(shù)組a中的所有元素,同時指針pa指向a[]的下一個單元
      ……
      ……

      數(shù)組名和數(shù)組指針變量作函數(shù)參數(shù)

        在第五章中曾經介紹過用數(shù)組名作函數(shù)的實參和形參的問題。在學習指針變量之后就更容易理解這個問題了。 數(shù)組名就是數(shù)組的首地址,實參向形參傳送數(shù)組名實際上就是傳送數(shù)組的地址, 形參得到該地址后也指向同一數(shù)組。 這就好象同一件物品有兩個彼此不同的名稱一樣。同樣,指針變量的值也是地址, 數(shù)組指針變量的值即為數(shù)組的首地址,當然也可作為函數(shù)的參數(shù)使用。
      float aver(float *pa);
      main(){
      float sco[5],av,*sp;
      int i;
      sp=sco;
      printf(“ninput 5 scores:n”);
      for(i=0;i<5;i++) scanf(“%f”,&sco[i]);
      av=aver(sp);
      printf(“average score is %5.2f”,av);
      }
      float aver(float *pa)
      {
      int i;
      float av,s=0;
      for(i=0;i<5;i++) s=s+*pa++;
      av=s/5;
      return av;
      }

      指向多維數(shù)組的指針變量

      本小節(jié)以二維數(shù)組為例介紹多維數(shù)組的指針變量。

      一、多維數(shù)組地址的表示方法
      設有整型二維數(shù)組a[3][4]如下:
      0 1 2 3
      4 5 6 7
      8 9 10 11
         設數(shù)組a的首地址為1000,各下標變量的首地址及其值如圖所示。在第四章中介紹過, C語言允許把一個二維數(shù)組分解為多個一維數(shù)組來處理。因此數(shù)組a可分解為三個一維數(shù)組,即a[0],a[1],a[2]。每一個一維數(shù)組又含有四個元素。例如a[0]數(shù)組,含有a[0][0],a[0][1],a[0][2],a[0][3]四個元素。 數(shù)組及數(shù)組元素的地址表示如下:a是二維數(shù)組名,也是二維數(shù)組0行的首地址,等于1000。a[0]是第一個一維數(shù)組的數(shù)組名和首地址,因此也為1000。*(a+0)或*a是與a[0]等效的, 它表示一維數(shù)組a[0]0 號元素的首地址。 也為1000。&a[0][0]是二維數(shù)組a的0行0列元素首地址,同樣是1000。因此,a,a[0],*(a+0),*a?amp;a[0][0]是相等的。同理,a+1是二維數(shù)組1行的首地址,等于1008。a[1]是第二個一維數(shù)組的數(shù)組名和首地址,因此也為1008。 &a[1][0]是二維數(shù)組a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。 由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。 此外,&a[i]和a[i]也是等同的。因為在二維數(shù)組中不能把&a[i]理解為元素a[i]的地址,不存在元素a[i]。

        C語言規(guī)定,它是一種地址計算方法,表示數(shù)組a第i行首地址。由此,我們得出:a[i],&a[i],*(a+i)和a+i也都是等同的。另外,a[0]也
      可以看成是a[0]+0是一維數(shù)組a[0]的0號元素的首地址, 而a[0]+1則是a[0]的1號元素首地址,由此可得出a[i]+j則是一維數(shù)組a[i]的j號元素首地址,它等于&a[i][j]。由a[i]=*(a+i)得a[i]+j=*(a+i)+j,由于*(a+i)+j是二維數(shù)組a的i行j列元素的首地址。該元素的值等于*(*(a+i)+j)。
      [Explain]#define PF “%d,%d,%d,%d,%d,n”
      main(){
      static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
      printf(PF,a,*a,a[0],&a[0],&a[0][0]);
      printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);
      printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);
      printf(“%d,%dn”,a[1]+1,*(a+1)+1);
      printf(“%d,%dn”,*(a[1]+1),*(*(a+1)+1));
      }

      二、多維數(shù)組的指針變量

        把二維數(shù)組a 分解為一維數(shù)組a[0],a[1],a[2]之后,設p為指向二維數(shù)組的指針變量??啥x為: int (*p)[4] 它表示p是一個指針變量,它指向二維數(shù)組a 或指向第一個一維數(shù)組a[0],其值等于a,a[0],或&a[0][0]等。而p+i則指向一維數(shù)組a[i]。從前面的分析可得出*(p+i)+j是二維數(shù)組i行j 列的元素的地址,而*(*(p+i)+j)則是i行j列元素的值。

        二維數(shù)組指針變量說明的一般形式為: 類型說明符 (*指針變量名)[長度] 其中“類型說明符”為所指數(shù)組的數(shù)據(jù)類型?!?”表示其后的變量是指針類型。 “長度”表示二維數(shù)組分解為多個一維數(shù)組時, 一維數(shù)組的長度,也就是二維數(shù)組的列數(shù)。應注意“(*指針變量名)”兩邊的括號不可少,如缺少括號則表示是指針數(shù)組(本章后面介紹),意義就完全不同了。
      [Explain]main(){
      static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
      int(*p)[4];
      int i,j;
      p=a;
      for(i=0;i<3;i++)
      for(j=0;j<4;j++) printf(“%2d “,*(*(p+i)+j));
      }
      ‘Expain字符串指針變量的說明和使用字符串指針變量的定義說明與指向字符變量的指針變量說明是相同的。只能按對指針變量的賦值不同來區(qū)別。 對指向字符變量的指針變量應賦予該字符變量的地址。如: char c,*p=&c;表示p是一個指向字符變量c的指針變量。而: char *s=”C Language”;則表示s是一個指向字符串的指針變量。把字符串的首地址賦予s。
      請看下面一例。
      main(){
      char *ps;
      ps=”C Language”;
      printf(“%s”,ps);
      }
      運行結果為:
      C Language
      上例中,首先定義ps是一個字符指針變量, 然后把字符串的首地址賦予ps(應寫出整個字符串,以便編譯系統(tǒng)把該串裝入連續(xù)的一塊內存單元),并把首地址送入ps。程序中的: char *ps;ps=”C Language”;等效于: char *ps=”C Language”;輸出字符串中n個字符后的所有字符。
      main(){
      char *ps=”this is a book”;
      int n=10;
      ps=ps+n;
      printf(“%sn”,ps);
      }
      運行結果為:
      book 在程序中對ps初始化時,即把字符串首地址賦予ps,當ps= ps+10之后,ps指向字符“b”,因此輸出為”book”。
      main(){
      char st[20],*ps;
      int i;
      printf(“input a string:n”);
      ps=st;
      scanf(“%s”,ps);
      for(i=0;ps[i]!=’