Introduction to the C Programming Language 指標 (Pointer)
指 標 (Pointer) 指標概述 指標的宣告與定義 指向指標的指標—雙重指標 指標與陣列 指標與函數
指標概述 C語言提供一種存取變數的特殊方式--指標(pointer),透過指標,可以不必用到變數的名稱,卻可以存取到變數的內容. 指標其實只是一種特殊的變數,用來存放變數在記憶體中的位址. 利用指標變數,可以把變數在記憶體內的位址存入指標中,可利用指標先找到該變數的位址,再由該位址取出位址內所儲存的變數值.這種依位址來取值的特殊方式,稱之為“間接定址取值法” 指標ptr存放了變數a的位址,也就是指標ptr指向變數a。 變數內容 5 FDD4 FDD2 FDD4 FDD6 FDD8 一般變數 a 指標變數 ptr ( 圖一 : 指標與變數在記憶體中的情形 )
指標的宣告與定義 指標變數宣告格式 例一: int *ptr ; /* 宣告指向整數的指標變數ptr ,它所存放的 資料型態 *指標變數 ; (1) 在變數的前面加上指標符號「*」,即是將變數宣告 成指標變數。 (2) 指標變數之前的資料型態,則是代表指標所指向之變 數的型態。 例一: int *ptr ; /* 宣告指向整數的指標變數ptr ,它所存放的 位址必須是一個整數變數的位址。 */ 資料型態 *指標變數 ;
指標的宣告與定義 例二: int *ptr ; /* 宣告指向整數的指標變數ptr */ int num=20 ; /*宣告整數變數num,並設值為12 */ ptr=&num ; /*把指標ptr設為變數num的位址, 即把ptr指向num */ ptr指向整數變數num 20 1408 1400 變數num 指標變數ptr 指標變數ptr的位址 變數num的位址
指標變數的使用 指標變數使用方式 位址運算子「 &」 : 用來取得變數的記憶體位址 位址取值運算子「 *」 : 用來取得指標所指向變數的內容 int num=20 ; 變數num 20 &num可取出變數num的位址,即 1400 1400 變數num的位址 int num=20; int *ptr=# 20 1408 1400 變數num 指標變數ptr 指標變數ptr的位址 變數num的位址 *ptr可取出ptr所指向之變數num的值(num的值為20)
指標變數的宣告 範例一:指標變數的宣告 Output: num=20,&num=ffd6 #include<stdio.h> #include<stdlib.h> int main(void) { int *ptr,num=20; /*宣告變數num與指標變數ptr */ ptr=# /*將num位址設給指標ptr存放 */ printf(“num=%d,&num=%x\n”,num,&num); printf(“*ptr=%d,ptr=%x,&ptr=%x\n”,*ptr,ptr,&ptr); system(“pause”); return 0; } Output: num=20,&num=ffd6 *ptr=20,ptr=ffd6,&ptr=ffd4
指標的宣告與定義 範例二: 比較輸出指標的位址與值 Output: a=20, *ptr=20, b=20 #include<stdio.h> void main() { int *ptr; int a,b; a=20; ptr=&a; /* 將 ptr 指向變數 a 的位址 */ b=*ptr; /* 將 b設定為 ptr 所指位址的內容值 */ printf(“a=%d,*ptr=%d , b=%d\n", a,*ptr , b ); printf(“ptr=%x , &a=%x\n", ptr , &a ); } Output: a=20, *ptr=20, b=20 ptr=ffd6 ,&a=ffd6
指向指標的指標—雙重指標 雙重指標宣告方式 資料型態 **指標變數; 例 : int **ptri; /*宣告一個指向整數的雙重指標ptri */ 資料型態 **指標變數; 位址 整數值 指向整數的指標 變數 1200 1460 5 雙重指標 指標變數 一般變數 1000 雙重指標
指向指標的指標—雙重指標 範例三: 雙重指標 , 輸出其內容及位址 #include<stdio.h> void main() { int *ptr1,**ptr2; int a=10; ptr1=&a; /* 指標 ptr1指向 a 的位址 */ ptr2=&ptr1; /* 雙重指標 ptr2 指向 ptr1的位址 */ printf("a=%d , &a=%x\n", a , &a ); printf("*ptr1=%d , ptr1=%x\n", *ptr1 , ptr1 ); printf("**ptr2=%d , *ptr2=%x\n", **ptr2 , *ptr2); printf("ptr2=%x, &ptr1=%x\n", ptr2 , &ptr1); } a ffd4 ffd6 5 **ptr2 *ptr1 ffd2 Output: a=10, &a=ffd6 *ptr1=10, ptr1=ffd6 **ptr2=10 ,*ptr=ffd6 ptr2=ffd4 , &ptr1=ffd4
指標與陣列 陣列事實上也是指標的一種應用,不同的是,陣列是固定長度的記憶體區塊;而指標是一個變數,用來記錄所指變數的位址. 利用index即可取出陣列的元素值,除了用index外,也可另外利用指標取出陣列的元素值. char a[10]; /*宣告陣列*/ char *pa; /*宣告指標*/ pa=&a[0]; 或 pa=a; /*指標指向陣列的開頭(第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指向陣列的開頭
指標與陣列 指標陣列 如何建立一個儲存字串的陣列?除了用二維的字元陣列處理,另外可用“指標陣列”來解決,用指標陣列來處理,會較節省記憶體空間. 指標陣列宣告格式 : 型態 *陣列名稱[個數 ] Name[0] Name[1] Name[2] D a v i d \0 J n e W g T o m L FDB2 FDB4 FBD6 ( 圖 三 : 儲存字串的二維字元陣列儲存方式 ) Name[0] Name[1] Name[2] FDB2 FDB4 FBD6 D a v i d \0 J n e W g T o m L ( 圖 四 : 指標陣列儲存方式 )
指標與陣列 範例五: 指標陣列 #include <stdio.h> int main(void) { int i; char *name[3]={"David","Jane Wang","Tom Lee"}; for(i=0;i<3;i++) /* 印出指標陣列的內容 */ printf("name[%d]=%s\n",i,name[i]); return 0; }
指標與函數 在函數中,若是想傳回某個結果給原呼叫函數,可利用return敘述,但當程式需要傳遞兩個以上的值時,就無法利用return敘述,此時可利用“指標”解決函數間傳遞多個回傳值的問題. 宣告函數原型範例 : int func ( int * , char * ) ; /* 將指標當成引數,傳入函數 */ 函數定義中接收參數部分,假設接收的變數名稱為 ptr1及 ptr2,記得在變數名稱前要加指標符號 * int func ( int * ptr1 , char * ptr2 ) ;
傳入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(“(call by value: x=%d , y=%d \n", x , y ); swap(&x,&y); printf(“(call by address: x=%d , y=%d \n", x , y ); } 傳入pointer值(變數位址即為pointer的值)
指標與函數 接上頁(範例六) void noswap ( int a , int b ) /* call by value */ { int t; t=a; a=b; b=t; } void swap ( int *a , int *b) /* call by address* / t=*a; *a=*b; *b=t;