指針:一個變量的地址 指針變量:一個變量專門用來存放另一個變量的地址(即指針)
存放地址的變量 例子: #includeint main() { int a=100,b=10;//定義整型變量並且初始化 int *pointer_1,*pointer_2;//定義指向整型數據的指針變量 pointer_1,pointer_2 pointer_1=&a;//變量a的地址賦值給指針pointer_1 pointer_2=&b; printf("a=%d,b=%d\n",a,b); printf("*pointer_1=%d,*pointer_2=%d\n",*pointer_1,*pointer_2); return 0; }
怎麼定義指針變量: 類型名 *指針變量名;(指針變量的基類型用來制定此指針變量可以指向的變量的類型)
怎麼引用指針變量
通過指針引用數組 所謂數組元素的指針就是數組元素的地址 例如: int a[10]={,1,3,5,7,9,11,13,15,17,19} int *p; p=&a[0];//和p=a等價 數組名不代表整個數組,只代表數組首元素的地址 p=a的作用是把a數組的首元素的地址賦給指針變量p,而不是把數組a各元素的值賦給p
指針運算符 (1)取地址運算符& 取地址運算符&是單目運算符,其結合性為自右至左,其功能是取變量的地址。在scanf函數及前面介紹指針變量賦值中,我們已經了解並使用了&運算符。 (2)取內容運算符* 取內容運算符*是單目運算符,其結合性為自右至左,用來表示指針變量所指的變量。在*運算符之後跟的變量必須是指針變量。需要注意的是指針運算符*和指針 變量說明中的指針說明符* 不是一回事。在指針變量說明中,“*”是類型說明符,表示其後的變量是指針類型。而表達式中出現的“*”則是一個運算符用以表示指 針變量所指的變量。 main(){ int a=5,*p=&a; printf ("%d",*p); } ...... 表示指針變量p取得了整型變量a的地址。本語句表示輸出變量a的值。
指針變量的運算 (1)賦值運算 指針變量的賦值運算有以下幾種形式: ①指針變量初始化賦值,前面已作介紹。 ②把一個變量的地址賦予指向相同數據類型的指針變量。例如: int a,*pa; pa=&a; ③把一個指針變量的值賦予指向相同類型變量的另一個指針變量。如: int a,*pa=&a,*pb; pb=pa; 由於pa,pb均為指向整型變量的指針變量,因此可以相互賦值。 ④把數組的首地址賦予指向數組的指針變量。 例如: int a[5],*pa; pa=a; (數組名表示數組的首地址,故可賦予指向數組的指針變量pa) 也可寫為: pa=&a[0]; 當然也可采取初始化賦值的方法: int a[5],*pa=a; ⑤把字符串的首地址賦予指向字符類型的指針變量。例如: char *pc;pc="c language";或用初始化賦值的方法寫為: char *pc="C Language"; 這裡應說明的是並不是把整個字符串裝入指針變量, 而是把存放該字符串的字符數組的首地址裝入指針變量。 在後面還將詳細介紹。 ⑥把函數的入口地址賦予指向函數的指針變量。例如: int (*pf)();pf=f; (2)加減算術運算 對於指向數組的指針變量,可以加上或減去一個整數n。設pa是指向數組a的指針變量,則pa+n,pa- n,pa++,++pa,pa--,--pa 運算都是合法的。 指針變量加或減一個整數n的意義是把指針指向的當前位置(指向某數組元素)向前或向後移動n個位置。應該注意,數組指針變量向前或向後移 動一個位置和地址加1或減1 在概念上是不同的。因為數組可以有不同的類型, 各種類型的數組元素所占的字節長度是不同的。如指針變量加1,即向後移動1 個位置表示指針變量指向下一個數據元素的首地址。 而不是在原地址基礎上加1。 例如: int a[5],*pa; pa=a; pa=pa+2; 指針變量的加減運算只能對數組指針變量進行, 對指向其它類型變量的指針變量作加減運算是毫無意義的。 (3)兩個指針變量之間的運算只有指向同一數組的兩個指針變量之間才能進行運算, 否則運算毫無意義。 ①兩指針變量相減 兩指針變量相減所得之差是兩個指針所指數組元素之間相差的元素個數。實際上是兩個指針值(地址) 相減之差再除以該數組元素的長度(字節數)。例如pf1和pf2 是指向同一浮點數組的 兩個指針變量,設pf1的值為2010H,pf2的值為2000H,而浮點數組每個元素占4個字節,所以pf1-pf2的結果為 (2000H-2010H)/4=4,表示pf1和 pf2之間相差4個元素。兩個指針變 量不能進行加法運算。 例如, pf1+pf2是什麼意思呢?毫無實際意義。 ②兩指針變量進行關系運算 指向同一數組的兩指針變量進行關系運算可表示它們所指數組元素之間的關系。例如: pf1==pf2表示pf1和pf2指向同一數組元素 pf1>pf2表示pf1處於高地址位置 pf1 main(){ int a=10,b=20,s,t,*pa,*pb; pa=&a; pb=&b; s=*pa+*pb; t=*pa**pb; printf("a=%d/nb=%d/na+b=%d/na*b=%d/n",a,b,a+b,a*b); printf("s=%d/nt=%d/n",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=%d/nmin=%d/n",*pmax,*pmin); } ...... pmax,pmin為整型指針變量。 輸入提示。 輸入三個數字。 如果第一個數字大於第二個數字... 指針變量賦值 指針變量賦值 指針變量賦值 指針變量賦值 判斷並賦值 判斷並賦值 輸出結果 ...... 數組指針變量的說明和使用 指向數組的指針變量稱為數組指針變量。 在討論數組指針變量的說明和使用之前,我們先明確幾個關系。 一個數組是由連續的一塊內存單元組 成的。 數組名就是這塊連續內存單元的首地址。一個數組也是由各個數組元素(下標變量) 組成的。每個數組元素按其類型不同占有幾個連續的內存單元。 一個數組元素的首地址也是指它所占有的幾個內存單元的首地址。 一個指針變量既可以指向一個數組,也可以指向一個數組元素, 可把數組名或第一個元素的地址賦予它。如要使指針變量 指向第i號元素可以把i元素的首地址賦予它或把數組名加i賦予它。 設有實數組a,指向a的指針變量為pa,從圖6.3中我們可以看出有以下關系: pa,a,&a[0]均指向同一單元,它們是數組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]=%d/n",i,a[i]); } printf("/n"); } 主函數 定義一個整型數組和一個整型變量 循環語句 給數組賦值 打印每一個數組的值 ...... 輸出換行 ...... 數組指針變量說明的一般形式為: 類型說明符 * 指針變量名 其中類型說明符表示所指數組的類型。 從一般形式可以看出指向數組的指針變量和指向普通變量的指針變量的說明是相同的。 引入指針變量後,就可以用兩種方法來訪問數組元素了。 第一種方法為下標法,即用a[i]形式訪問數組元素。 在第四章中介紹數組時都是采用這種方法。 第二種方法為指針法,即采用*(pa+i)形式,用間接訪問的方法來訪問數組元素。 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]=%d/n",i,*pa); pa++; } } 主函數 定義整型數組和指針 將指針pa指向數組a 循環 將變量i的值賦給由指針pa指向的a[]的數組單元 將指針pa指向a[]的下一個單元 ...... 指針pa重新取得數組a的首地址 循環 用數組方式輸出數組a中的所有元素 將指針pa指向a[]的下一個單元 ...... ...... 下面,另舉一例,該例與上例本意相同,但是實現方式不同。 main(){ int a[5],i,*pa=a; for(i=0;i<5;){ *pa=i; printf("a[%d]=%d/n",i++,*pa++); } } 主函數 定義整型數組和指針,並使指針指向數組a 循環 將變量i的值賦給由指針pa指向的a[]的數組單元 用指針輸出數組a中的所有元素,同時指針pa指向a[]的下一個單元 ...... ......
數組名和數組指針變量作函數參數 介紹過用數組名作函數的實參和形參的問題。在學習指針變量之後就更容易理解這個問題了。 數組名就是數組的首地址,實參向形參傳送數組名實際上就是傳送數組的地址, 形參得到該地址後也指向同一數組。 這就好象同一件物品有兩個彼此不同的名稱一樣。同樣,指針變量的值也是地址, 數組指針變量的值即為數組的首地址,當然也可作為函數的參數使用。 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; }
多維數組
例子: #includeint main(){ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; printf("%d,%d\n",a,*a); //0行首地址和0行0列元素地址 printf("%d,%d\n",a[0],*(a+0)); //0行和0列元素地址 printf("%d,%d\n",&a[0],&a[0][0]); //0行首地址和0行0列元素地址 printf("%d,%d\n",a[1],a+1); //1行0列元素地址和1行地址 printf("%d,%d\n",&a[1][0],*(a+1)+0); //1行0列元素地址 printf("%d,%d\n",a[1][0],*(*(a+1))+0); //1行0列元素的值 printf("%d,%d\n",*a[2],*(*(a+2)+0)); //2行0列元素的值 return 0; }
通過指針引用字符串元素 例如: #includeint main() { char *string ="I Love China!"; prinft("%s\n",string); return 0; } 運行結果: I Love China!
指針數組和多重指針 指針數組:一個數組,若其元素均為指針類型數據 一般形式:類型名 *數組名[數組的長度]