Introduction to the C Programming Language 指標 (Pointer)
指 標 (Pointer) 指標變數所存放的內容為記憶體位置,而指標變數在記憶體中佔幾個記憶體位元組,則視所使用的語言系統而定,以Turbo C而言是2個位元組. 宣告指標變數時,需在變數名稱前加個 * 號以玆識別. * 號除了在指標變數宣告時使用外,最主要是用來存取pointer所指到的變數值. 例: *pa=0; [ 將0存入pa所指的變數內 ] y=*pa; [ 取pa所指的變數值(0),再設給y ] pa=&x; [ 以&符號取得x的位址,存入pa(把pa指向x) ] y=*pa; [ 把pa所指的變數存入y ] 若指標沒指到任何一個位置,其初值要設為NULL,NULL在stdlib.h,stdio.h,stddef.h,mem.h,alloc.h的標頭檔皆有定義. 一.若指標沒指到任一個位置範例說明: #include<stddef.h> void main(void) { char *p=NULL; …. If(p!=NULL) …..
指 標 (Pointer) 範例一: 指標的運算 #include<stdio.h> void main() { int *ptr,i,val; i=20; ptr=&i; val=*ptr; printf("val=%d\n",val); } ptr 所指的位址等於 i 的位址 檔名 : P1.c 一.執行結果: val:20 二.參考來源 : Borland C++入門與應用.徹底剖析 (P.214)
指 標 (Pointer) 範例二: 指標的應用 #include<stdio.h> main() { int a=3,b=4; int *fp; printf("The original values are: a=%d , b=%d \n" , a , b ); printf("The Address are : &a=0x%p , &b=0x%p \n", &a , &b ); fp=&a; *fp=100; printf( "passing *fp=100 , a value change=%d \n" , a ); fp=&b; printf("passing fp=&b , fp value change=%d\n", *fp ); } 宣告 : fp 是指向整數變數的pointer 以 & 取得 a 變數的位址, 將位址設給 fp ( fp 指向a) 檔名 : P2.c 一.執行結果: The original values are : a=3 , b=4 The Address are : a=0xFFDA , b=0xFFDC passing *fp=100 , a value change=100 passing fp=&b , fp value change=4 二. &a=0x%p 其中的%p控制印出16進位 三. * operator : A. 用來取pointer所指的變數(位址)內含值 B. 也稱為indirect operator & operator : A.用來取變數位址 B.也稱為address operator 四.參考來源 : C語言入門 (P.8-8) 把100存入 fp 所指的變數內 以 & 取得 b 變數的位址, 將位址設給 fp ( fp 轉指向b) 利用 * 號 間接取值
傳入pointer值(變數位址即為pointer的值) 以指標來傳引數 範例三:設計一個傳值函式noswap(),及一個傳址函式swap(), 將從主程式傳來的兩個正數引數值互相對調 #include<stdio.h> main() { int x=2,y=3; void noswap(int a , int b ); void swap( int *a , int *b ); printf("The original values are: x=%d , y=%d \n" , x , y ); noswap(x,y); printf("The x y are changed : x=%d , y=%d \n", x , y ); swap(&x,&y); } 檔名 : P3.c 一.執行結果: The original values are : x=2 , y=3 The x y are changed : x=2 , y=3 The x y are changed : x=3 , y=2 二.到C語言呼叫函式預設是採傳值呼叫(call by value), 若要交換兩數字,必須將x,y的位址傳給函式, 才能直接接觸到x,y變數,所以要透過pointer才能達到. 三.參考來源 : C語言入門 (P.8-11) 傳入pointer值(變數位址即為pointer的值)
以指標來傳引數 接上頁(範例三) void noswap ( int a , int b ) { int t; t=a; a=b; b=t; } void swap ( int *a , int *b) t=*a; *a=*b; *b=t;
指位器的指位器 指標(pointer)也可以指向指標,可稱為“指位器的指位器“ 指位器的指位器的宣告方式: int **pa; 亦可寫成 int*(*pa) [ pa是一個pointer,它指向一個整數的pointer ]
以指標來傳引數 範例四: 指標以位址傳遞(call by address) #include<stdio.h> main() { int a=1,b=2,*p,*q; void sub( int ** , int ** ); p=&a; q=&b; sub(&p,&q); printf("a=%d b=%d \n" , *p , *q ); } void sub ( int **x , int **y ) *x=*y; } 檔名 : P4.c 一.執行結果: a=2 b=2 二.雙星號** 代表指標變數的位址傳遞 三.參考來源 : C入門與Turbo系統(P.12-6)
指標與陣列的關係 在C語言裡,指標與陣列的關係密不可分,兩者的差別是:陣列是固定長度的連續實體,而指標則是用來記錄位址的單一變數. 建立指標與陣列的關係 char a[10]; /*宣告陣列*/ pa=&a[0]; /*第一個指標指向陣列的開頭(第0個元素)*/ 以此為基點用索引的方式來取得陣列的每個元素 *(pa) 取到的是陣列的第0個元素 a[0] *(pa+1) 取到的是陣列的第1個元素 a[1] *(pa+i)取到的是陣列的第i個元素 a[i]
指標與陣列的關係 範例五: 用指標取出陣列元素的位址 #include<stdio.h> main() { int i; char *pa; char a[4]={'A','B','C','D'}; pa=a; for(i=0;i<4;i++) printf("a[%d] value:%c ; *(pa+%d) value:%c\n",i,a[i],i,*(pa+i)); printf("&[%d] address:%x ; *(pa+%d) address:%x\n",i,&a[i],i,pa+i); } Pointer指向陣列的開頭 檔名 : P5.c 一. 執行結果: a[0] value:A ; *(pa+0) value:A a[1] value:B ; *(pa+1) value:B a[2] value:C ; *(pa+2) value:C a[3] value:D ; *(pa+3) value:D &[0] address:ffe0 ; *(pa+0) address:ffe0 &[1] address:ffe1 ; *(pa+1) address:ffe1 &[2] address:ffe2 ; *(pa+2) address:ffe2 &[3] address:ffe3 ; *(pa+3) address:ffe3 二.a[I]與*(pa+i)所取得的是一樣的陣列元素值 三.&a[I]與pa+I所取得的是一樣的陣列元素位址 四.參考來源 : C語言實務(P.375-376舊版)
指標與陣列的關係 範例六: 利用指標將陣列元素相加 #include<stdio.h> void main() { int array[5]; int *ptr,i,sum; printf("Please enter 5 integer:\n"); for(i=0;i<5;i++) scanf("%d",&array[i]); sum=0; for(ptr=array;ptr<&array[5];ptr++) sum+=*ptr; printf("The sum of this array is %d\n",sum); } 檔名 : P6.c 執行結果: Please enter 5 integer: 1 2 3 4 5 The sum of this array is 15 二.參考來源 : Borland C++入門與應用.徹底剖析 (P.218)
指標與陣列的關係 範例七: 將數字由小到大排序(選擇排序法). #include<stdio.h> main() { void swap(int *a,int *b); void printArray(int n,int a[]); int a[] = {32,43,12,7,52,95,66,28}; int i,j,min,t; printf("The original Array:"); printArray(8,a); for(i=0;i<8;i++) for(j=min=i;j<8;j++) if(a[j]<a[min]) min=j; swap(&a[min],&a[i]); } printf("The sorted Array:"); 一 .檔名 : P7.c 二.執行結果: The original Array: 32 43 12 7 52 95 66 28 The sorted Array: 7 12 28 32 43 52 66 95 三.將兩個整數位址傳至void swap(int *a,int *b),將所指的內容互相交換. 四.參考來源 : C語言入門(P.8-22至P.8-26)
指標與陣列的關係 接上頁(範例七) void swap(int *a,int *b) { int t; t=*a; *a=*b; *b=t; } void printArray(int n,int b[]) int i; for(i=0;i<n;i++) printf("%5d",b[i]); printf("\n");
指位器陣列 陣列的元素也可以是pointer,這種陣列叫做“指位器陣列” 指位器陣列對於不定長度的資料處理非常有用,因陣列是固 定的存放空間,資料搬動很不方便,可採指位器陣列來解決 問題 指位器陣列的宣告方式: char *p[m]; [ p是一個陣列,其元素是字元的pointer ]
指位器陣列 範例八: 指位器陣列的使用--字串排序 #include<stdio.h> #include<string.h> #define SIZE 100 void main() { char s[SIZE][SIZE]; char *line[SIZE]; char *p; int i,j,k; for (i=0;i<SIZE;i++) printf("%d:",i++) get(s[i]); if(strcmp(s[i],"q")==0) break; line[i]=s[i]; } 檔名 :P8.c 一.並未真正搬動字串來排序,而是更動pointer所指的對象, 來達到排序的效果,執行速度會比較快. 二.strcmp( ) 是標準函式庫的成員之一,其宣告的內容放在string.h之中, strcmp( ) 的功能是比較兩個字串引數是否相同,相同時傳回0; 若第一個字串大於第二個字串,則傳回大於0的值; 若第一個字串小於第二個字串,則傳回小於0的值. 三.若字串中含有空白字元,則應以gets( )函數來做字串資料的輸入, 字串資料以gets( )函數輸入時,換行符號 \n 並不會放到字串裡. 四. 參考來源 : C語言學習實務(P.8-36~P.8-40新版) C入門與Turbo系統 (P.9-6)
指位器陣列 接上頁(範例八) for (j=0;j<i-1;j++) for (k=j+1;k<i;k++) if (strcmp(line[j],line[k] )>0) { p=line[k]; line[k]=line[j]; line[j]=p; } printf("\nSorting...\n"); for(j=0;j<i;j++) printf("%d:%s\n",j+1,lint[j]); 執行結果: 1:liu 2:wang 3:lin 4:shih 5:chang 6:q Sorting... 1:chang 2:lin 3:liu 5:wang