c 程式設計 指標 - 國立中興大學hwtseng/visualcpp_slide/point.pdf · 課程大綱...
TRANSCRIPT
-
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;
1012
3
1000
1004
1008
1012
ptr是一個指向整數型態的指標, 內容為該整數的位址
i是一個整數, 內容為3, 與*ptr的值一樣
記憶體位址
-
取址運算子與指標運算子(1)
&是取址運算子用來取得該變數在記憶體的位址
&變數名稱
int i=3;int *ptr;ptr=&i;
1012
3
1000
1004
1008
1012
記憶體位址 ptr是一個整數指標
*ptr取得該指標的內容值
&i取得該整數在記憶體中的位址
i是一個整數
-
取址運算子與指標運算子(2)
*是指標運算子用來取得指標所指向位址的內容值
*指標變數名稱
int i;int *p;p=&i;
*p=50
記憶體位址 記憶體位址
1012
50
1012
??
10001000
10041004
10081008
10121012
-
練習時間
每一種資料型態的指標變數在32位元的作業系統環境中都佔用4個bytes,因為指標變數存放的是記憶體位址
比較輸出指標的位址與值.
-
指標運算 (1)
指定運算錯誤:int *p=10; 正確:
int x=10;int *p=&x;Int *p = (int *)10;
加減運算
比較運算
差值運算
變數
int x = 10;
指標變數
int *x = (int *)10;
x 10 *x10&x x
-
指標運算 (2)
加減運算
只能加常數值
將指標變數內容『加1』依據指標指向的資料型態所佔用的記憶體單位大小,來決定移動多少個位址(加1代表加1個單位),以便指向正確的下一筆同樣資料類型的資料。
例子
int *p,*q;
p=p+q; /* 不合法 */
-
指標運算 (3)
比較運算
相同型態的指標變數可以做比較運算,藉由比較運算,我們可以得知記憶體位址的先後關係
較早配置記憶體的變數位於較高的記憶體位址
例子
-
指標運算 (4)
差值運算
兩個相同資料型態的指標變數可以做減法運算
代表兩個記憶體位址之間的可存放多少個該資料型態的資料
例子
-
傳址呼叫 (1)
傳值呼叫
call by value
傳址呼叫
call by address
-
1 /* Fig. 7.6: fig07_06.c 2 Cube a variable using call-by-value */ 3 #include 4
5 int cubeByValue( int n ); /* prototype */ 6
7 int main() 8 { 9 int number = 5; /* initialize number */ 10
11 printf( "The original value of number is %d", number ); 12 13 /* pass number by value to cubeByValue */ 14 number = cubeByValue( number ); 15
16 printf( "\nThe new value of number is %d\n", number ); 17
18 return 0; /* indicates successful termination */ 19
20 } /* end main */ 21
22 /* calculate and return cube of integer argument */ 23 int cubeByValue( int n ) 24 { 25 return n * n * n; /* cube local variable n and return result */ 26 27 } /* end function cubeByValue */
Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
-
The original value of number is 5The new value of number is 125
Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
-
int main()
{
int number = 5;
number=cubeByValue(number);
}
int cubeByValue( int n )
{
return n * n * n;
}
number
5
n
Before main calls cubeByValue :
undefined
After cubeByValue receives the call:
int main()
{
int number = 5;
number = cubeByValue( number );
}
int cubeByValue( int n )
{
return n * n * n;
}
number
5
n
5
After cubeByValue cubes parameter n and before
125
int cubeByValue( int n )
{
return n * n * n;
}
int main()
{
int number = 5;
number = cubeByValue( number );
}
n
cubeByValue returns to main :
5
number
5
Analysis of a typical call-by-value. (Part 1 of 2.)
-
125
int main()
{
int number = 5;
number = cubeByValue( number );
}
int cubeByValue( int n ){
return n * n * n;
}
number
5
n
After cubeByValue returns to main and before assigning the result to number :
undefined
125125
int main()
{
int number = 5;
number = cubeByValue( number );
}
int cubeByValue( int n )
{
return n * n * n;
}
number
125
n
After main completes the assignment to number :
undefined
Analysis of a typical call-by-value. (Part 2 of 2.)
-
1 /* Fig. 7.7: fig07_07.c 2 Cube a variable using call-by-reference with a pointer argument */ 3
4 #include 5
6 void cubeByReference( int *nPtr ); /* prototype */ 7
8 int main() 9 { 10 int number = 5; /* initialize number */ 11
12 printf( "The original value of number is %d", number ); 13 14 /* pass address of number to cubeByReference */ 15 cubeByReference( &number ); 16
17 printf( "\nThe new value of number is %d\n", number ); 18
19 return 0; /* indicates successful termination */ 20
21 } /* end main */ 22
23 /* calculate cube of *nPtr; modifies variable number in main */ 24 void cubeByReference( int *nPtr ) 25 { 26 *nPtr = *nPtr * *nPtr * *nPtr; /* cube *nPtr */ 27 } /* end function cubeByReference */
傳入變數位址
將變數改為指標型態
傳入型態為指標
Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
-
The original value of number is 5The new value of number is 125
Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
-
void cubeByReference( int *nPtr ){
*nPtr = *nPtr * *nPtr * *nPtr;
}
int main()
{
int number = 5;
cubeByReference( &number );
}
void cubeByReference( int *nPtr ){
*nPtr = *nPtr * *nPtr * *nPtr;
}
int main()
{
int number = 5;
cubeByReference( &number );
}
number
5
nPtr
number
5
nPtr
Before main calls cubeByReference :
After cubeByReference receives the call and before *nPtr is cubed:
undefined
call establishes this pointer
125
void cubeByReference( int *nPtr ){
*nPtr = *nPtr * *nPtr * *nPtr;
}
int main()
{
int number = 5;
cubeByReference( &number );
}
number
125
nPtr
After *nPtr is cubed and before program control returns to main :
called function modifies caller’s variable
Analysis of a typical call-by-reference with a pointer argument.
-
練習時間#include
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代表下一個位址.
陣列其實也是指標的一種應用.
-
1 /* Fig. 7.20: fig07_20.cpp 2 Using subscripting and pointer notations with arrays */ 3
4 #include 5
6 int main() 7 { 8 int b[] = { 10, 20, 30, 40 }; /* initialize array b */ 9 int *bPtr = b; /* set bPtr to point to array b */ 10 int i; /* counter */ 11 int offset; /* counter */ 12
13 /* output array b using array subscript notation */ 14 printf( "Array b printed with:\nArray subscript notation\n" ); 15
16 /* loop through array b */ 17 for ( i = 0; i < 4; i++ ) { 18 printf( "b[ %d ] = %d\n", i, b[ i ] ); 19 } /* end for */ 20
21 /* output array b using array name and pointer/offset notation */ 22 printf( "\nPointer/offset notation where\n" 23 "the pointer is the array name\n" ); 24
Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
-
25 /* loop through array b */ 26 for ( offset = 0; offset < 4; offset++ ) { 27 printf( "*( b + %d ) = %d\n", offset, *( b + offset ) ); 28 } /* end for */ 29
30 /* output array b using bPtr and array subscript notation */ 31 printf( "\nPointer subscript notation\n" ); 32
33 /* loop through array b */ 34 for ( i = 0; i < 4; i++ ) { 35 printf( "bPtr[ %d ] = %d\n", i, bPtr[ i ] ); 36 } /* end for */ 37
38 /* output array b using bPtr and pointer/offset notation */ 39 printf( "\nPointer/offset notation\n" ); 40
41 /* loop through array b */ 42 for ( offset = 0; offset < 4; offset++ ) { 43 printf( "*( bPtr + %d ) = %d\n", offset, *( bPtr + offset ) ); 44 } /* end for */ 45
46 return 0; /* indicates successful termination */ 47
48 } /* end main */
Copyright 1992-2004 by Deitel & Associates, Inc. and Pearson Edition Inc. All right Reserved.
-
Program Output
Array b printed with:Array subscript notationb[ 0 ] = 10b[ 1 ] = 20b[ 2 ] = 30b[ 3 ] = 40
Pointer/offset notation wherethe pointer is the array name*( b + 0 ) = 10*( b + 1 ) = 20*( b + 2 ) = 30*( b + 3 ) = 40
Pointer subscript notationbPtr[ 0 ] = 10bPtr[ 1 ] = 20bPtr[ 2 ] = 30bPtr[ 3 ] = 40
Pointer/offset notation*( bPtr + 0 ) = 10*( bPtr + 1 ) = 20*( bPtr + 2 ) = 30*( bPtr + 3 ) = 40
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][2] 跟 ptr[3*1+2]的比較
(*(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; /* 指向指標的指標 */int *** ptr; /* 三層指標變數 */
ptr *ptr **ptr位址 位址 整數值
雙重指標
-
指標的指標 (2)
-
指標的指標 (3)
使用多重指標(指標的指標)將九九乘法表的乘法結果儲存在9*9的二維整數陣列,並將陣列的資料列印出來
陣列表示法 指標表示法
array[i][j] *(*(array+i)+j)
-
問題:
請問下列程式的執行結果
#include #include 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
定義方式一
int main(int argc,char *argv[])定義方式二:
int main(int argc,char argv[][]) /* 使用二維字元陣列(字串陣列) */定義方式三:
int main(int argc,char **argv) /* 使用指標的指標 */
argc表示命令列中參數字串的個數.
argv表示指向命令列中所有參數字串的指標.
例子
-
動態記憶體配置
使用在某些陣列大小無法於事先決定的情況
C語言不能宣告一個陣列大小為變數的陣列需要用多少記憶體空間,就向系統要多少記憶體空間
於執行過程中配置一個適當大小的記憶體空間給指標,接著藉由這個指標來存取分配到的記憶體空間內的資料
-
配置記憶體函式-malloc( )
標頭檔:
#include #include 語法:void *malloc(size_t size);功能:動態配置記憶體
範例char *ptr;
ptr = (char *)malloc(sizeof(char)*9);
-
釋放記憶體函式-free( )
標頭檔:
#include #include 語法:void free(void *ptr);功能:釋放記憶體
範例:
Free(ptr);
我們透過malloc函式取得的記憶體,可以於不需再使用的狀況下,透過free函式將之歸還給系統
-
今天學到了什麼
什麼是指標
如何使用指標運算
如何使用函式的傳指標呼叫
如何使用指標和陣列
如何使用指標與函式
如何使用多重指標
如何使用main函式的引數串列與回傳值如何使用動態記憶體配置