C 程式設計— 指標
課程大綱 C語言簡介 基本資料型態, 變數, 基本輸入輸出 控制敘述- 選擇控制與重覆控制 陣列 函式 指標 字元與字串 結構 檔案處理
本次上課大綱 指標與記憶體位址 指標運算 函式的傳指標呼叫 指標和陣列 指標與函式 多重指標 main函式的引數串列與回傳值 動態記憶體配置
什麼是指標(pointer) 指標 一種變數 儲存記憶體位置 儲存在該記憶體中的可能是字元, 整數,指標本身變數的位置 程式可以間接取得該指標所指位址的變數值 節省記憶體空間 減少不必要的搬動 使用不當的話, 造成系統或程式嚴重的錯誤
存取記憶體內容
宣告指標變數 (1) 指標的宣告方式與變數的宣告方式相同, 只不過指標在變數前面多加一個 * 資料型態 *指標變數名稱 資料型態 *指標變數名稱 int *int_ptr; char *ch_ptr; float *float_ptr; double *double_ptr;
宣告指標變數 (2) int i=3; int *ptr; ptr=&i; ptr是一個指向整數型態的指標, 內容為該整數的位址 1012 3 1000 1004 1008 ptr是一個指向整數型態的指標, 內容為該整數的位址 i是一個整數, 內容為3, 與*ptr的值一樣 記憶體位址
取址運算子與指標運算子(1) &是取址運算子 用來取得該變數在記憶體的位址 &變數名稱 int i=3; int *ptr; ptr=&i; 1012 3 1000 1004 1008 記憶體位址 ptr是一個整數指標 *ptr取得該指標的內容值 &i取得該整數在記憶體中 的位址 i是一個整數
取址運算子與指標運算子(2) *是指標運算子 用來取得指標所指向位址的內容值 *指標變數名稱 int i; int *p; p=&i; 記憶體位址 記憶體位址 1012 1012 1000 1000 1004 1004 1008 1008 50 ?? 1012 1012
練習時間 每一種資料型態的指標變數在32位元的作業系統環境中都佔用4個bytes,因為指標變數存放的是記憶體位址 比較輸出指標的位址與值.
指標運算 (1) 指定運算 加減運算 比較運算 差值運算 錯誤:int *p=10; 正確: int x=10; int *p=&x; 變數 int x = 10; 指標變數 int *x = (int *)10; x 10 *x &x 10 x
指標運算 (2) 加減運算 只能加常數值 將指標變數內容『加1』 依據指標指向的資料型態所佔用的記憶體單位大小,來決定移動多少個位址(加1代表加1個單位),以便指向正確的下一筆同樣資料類型的資料。 例子 int *p,*q; p=p+q; /* 不合法 */
指標運算 (3) 比較運算 例子 相同型態的指標變數可以做比較運算,藉由比較運算,我們可以得知記憶體位址的先後關係 較早配置記憶體的變數位於較高的記憶體位址 例子
指標運算 (4) 差值運算 兩個相同資料型態的指標變數可以做減法運算 代表兩個記憶體位址之間的可存放多少個該資料型態的資料 例子
傳址呼叫 (1) 傳值呼叫 call by value 傳址呼叫 call by address
Copyright 1992-2004 by Deitel & Associates, Inc Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
The original value of number is 5 The new value of number is 125 Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
Analysis of a typical call-by-value. (Part 1 of 2.) Before main calls cubeByValue : int main() number int cubeByValue( int n ) { { int number = 5 ; 5 return n * n * n; } n number=cubeByValue(number); } undefined After cubeByValue receives the call: int main() int cubeByValue( int n ) number { { int number = 5 ; 5 return n * n * n; } number = cubeByValue( number ); n } 5 After cubeByValue cubes parameter n and before cubeByValue returns to main : int main() int cubeByValue( int n ) number { { 125 int number = 5 ; 5 return n * n * n; } number = cubeByValue( number ); n } 5 Analysis of a typical call-by-value. (Part 1 of 2.)
and before assigning the result to 125 int main() { number = 5 ; number = cubeByValue( number ); } cubeByValue( n ) return n * n * n; number n After cubeByValue returns to main and before assigning the result to : undefined completes the assignment to Analysis of a typical call-by-value. (Part 2 of 2.)
傳入型態為指標 傳入變數位址 將變數改為指標型態 Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
The original value of number is 5 The new value of number is 125 Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
receives the call and before is cubed: main calls cubeByReference : int main() number void cubeByReference( int *nPtr ) { { 5 int number = 5 ; *nPtr = *nPtr * *nPtr * *nPtr; } cubeByReference( &number ); nPtr } undefined After cubeByReference receives the call and before *nPtr is cubed: int main() number void cubeByReference( int *nPtr ) { { 5 int number = 5 ; *nPtr = *nPtr * *nPtr * *nPtr; } cubeByReference( &number ); nPtr call establishes this pointer } After *nPtr is cubed and before program control returns to main : int main() number void cubeByReference( int *nPtr ) { { 125 125 int number = 5 ; *nPtr = *nPtr * *nPtr * *nPtr; } cubeByReference( &number ); called function modifies nPtr } caller’s variable Analysis of a typical call-by-reference with a pointer argument.
練習時間 SWAP #include<stdio.h> void swap(int *,int *); int main() { int i,j; i=1,j=2; swap(&i,&j); printf("%d %d",i,j); } void swap(int *p,int *q) int temp; temp=*p,*p=*q;*q=temp; SWAP
傳址呼叫 (2) 傳值呼叫 傳址呼叫
指標與陣列 int array[10]; 我們以陣列名為array代表陣列的起始位址, 以array+1表示下一個位址. 當宣告指標時, int *ptr; 則以ptr代表其位址, 以ptr+1代表下一個位址. 陣列其實也是指標的一種應用.
Copyright 1992-2004 by Deitel & Associates, Inc Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
Copyright 1992-2004 by Deitel & Associates, Inc Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
Array b printed with: Array subscript notation b[ 0 ] = 10 b[ 1 ] = 20 b[ 2 ] = 30 b[ 3 ] = 40 Pointer/offset notation where the pointer is the array name *( b + 0 ) = 10 *( b + 1 ) = 20 *( b + 2 ) = 30 *( b + 3 ) = 40 Pointer subscript notation bPtr[ 0 ] = 10 bPtr[ 1 ] = 20 bPtr[ 2 ] = 30 bPtr[ 3 ] = 40 Pointer/offset notation *( bPtr + 0 ) = 10 *( bPtr + 1 ) = 20 *( bPtr + 2 ) = 30 *( bPtr + 3 ) = 40 Program Output Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
練習時間 陣列其實也是指標的一種應用. 如果用array++會怎樣? 使用指標控制陣列. 如果用ptr++會怎樣?
指標與二維陣列 例子 多重指標與二維陣列 int array[3][4], *ptr; ptr=(int *)array; (*(array+1))[1]跟*((array+1)[1])的比較 多重指標與二維陣列
指標陣列 陣列裡面所包含的元素都是指標. 指標陣列型態 例子: int *int_ptr[10]; // 整數指標陣列 float *float_ptr[10]; double *double_ptr[10]; char *str[10]; 例子:
指標與函數 函數的名稱與陣列的名稱一樣, 都代表著起始位址, 同時也是一個指標的常數, 因此函數指標可做如下的宣告: 例子: void (*func)(void); 例子: 傳回整數的指標函數: 如果把程式中第9行的 *func(i) 變成 func(i)的話, 會怎樣?
指標的指標 (1) int * ptr; /* 指標 */ int ** ptr; /* 指向指標的指標 */ 位址 位址 整數值 雙重指標
指標的指標 (2)
指標的指標 (3) 使用多重指標(指標的指標)將九九乘法表的乘法結果儲存在9*9的二維整數陣列,並將陣列的資料列印出來 陣列表示法 指標表示法 array[i][j] *(*(array+i)+j)
問題: 請問下列程式的執行結果 #include <stdio.h> #include <stdlib.h> int main() { int x[5]={2,4,6,8,10},*p,**pp; p=x; pp=&p; printf("%d\n",*(p)); p++; printf("%d\n",**pp); system("pause"); return 0; }
main()的argc與argv 定義方式一 定義方式二: 定義方式三: argc表示命令列中參數字串的個數. int main(int argc,char *argv[]) 定義方式二: int main(int argc,char argv[][]) /* 使用二維字元陣列(字串陣列) */ 定義方式三: int main(int argc,char **argv) /* 使用指標的指標 */ argc表示命令列中參數字串的個數. argv表示指向命令列中所有參數字串的指標. 例子
動態記憶體配置 使用在某些陣列大小無法於事先決定的情況 需要用多少記憶體空間,就向系統要多少記憶體空間 C語言不能宣告一個陣列大小為變數的陣列 需要用多少記憶體空間,就向系統要多少記憶體空間 於執行過程中配置一個適當大小的記憶體空間給指標,接著藉由這個指標來存取分配到的記憶體空間內的資料
配置記憶體函式-malloc( ) 標頭檔: 語法:void *malloc(size_t size); 功能:動態配置記憶體 範例 #include <stdlib.h> #include <malloc.h> 語法:void *malloc(size_t size); 功能:動態配置記憶體 範例 char *ptr; ptr = (char *)malloc(sizeof(char)*9);
釋放記憶體函式-free( ) 標頭檔: 語法:void free(void *ptr); 功能:釋放記憶體 範例: #include <stdlib.h> #include <malloc.h> 語法:void free(void *ptr); 功能:釋放記憶體 範例: Free(ptr); 我們透過malloc函式取得的記憶體,可以於不需再使用的狀況下,透過free函式將之歸還給系統
今天學到了什麼 什麼是指標 如何使用指標運算 如何使用函式的傳指標呼叫 如何使用指標和陣列 如何使用指標與函式 如何使用多重指標 如何使用main函式的引數串列與回傳值 如何使用動態記憶體配置