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
??
1000 1000 1004 1004
1008 1008
1012 1012
練習時間
每一種資料型態的指標變數在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
*x&x
10
x指標運算 (2)
加減運算
只能加常數值
將指標變數內容『加1』 依據指標指向的資料型態所佔用的記憶體單位大小,來決
定移動多少個位址(加1代表加1個單位),以便指向正確 的下一筆同樣資料類型的資料。
例子int *p,*q;
p=p+q; /* 不合法 */
指標運算 (3)
比較運算
相同型態的指標變數可以做比較運算,藉由比較運 算,我們可以得知記憶體位址的先後關係
較早配置記憶體的變數位於較高的記憶體位址 例子
指標運算 (4)
差值運算
兩個相同資料型態的指標變數可以做減法運算
代表兩個記憶體位址之間的可存放多少個該資料型 態的資料
例子傳址呼叫 (1)
傳值呼叫
call by value 傳址呼叫
call by address1 /* Fig. 7.6: fig07_06.c
2 Cube a variable using call-by-value */
3 #include <stdio.h>
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 5 The 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
maincalls
cubeByValue :undefined
After
cubeByValuereceives the call:
int main() {
int number = 5;
number = cubeByValue( number );
}
int cubeByValue( int n ) {
return n * n * n;
} number
5
n
5
After
cubeByValuecubes parameter
nand 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
cubeByValuereturns to
mainand before assigning the result to number
:undefined
125 125
int main() {
int number = 5;
number = cubeByValue( number );
}
int cubeByValue( int n ) {
return n * n * n;
} number
125
n
After
maincompletes 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 <stdio.h>
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 5 The 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
maincalls
cubeByReference :After
cubeByReferencereceives the call and before
*nPtris 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
*nPtris 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<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代表下一個位址.
陣列其實也是指標的一種應用.1 /* Fig. 7.20: fig07_20.cpp
2 Using subscripting and pointer notations with arrays */
3
4 #include <stdio.h>
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 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
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 <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
定義方式一 int main(int argc,char *argv[])
定義方式二: int main(int argc,char argv[][]) /* 使用二維字元陣列(字串陣列) */
定義方式三: int main(int argc,char **argv) /* 使用指標的指標 */
argc表示命令列中參數字串的個數.
argv表示指向命令列中所有參數字串的指標.
例子動態記憶體配置
使用在某些陣列大小無法於事先決定的情況
C語言不能宣告一個陣列大小為變數的陣列 需要用多少記憶體空間,就向系統要多少記憶 體空間
於執行過程中配置一個適當大小的記憶體空間
給指標,接著藉由這個指標來存取分配到的記
憶體空間內的資料
配置記憶體函式- malloc( )
標頭檔:
#include <stdlib.h>
#include <malloc.h> 語法:void *malloc(size_t size);
功能:動態配置記憶體
範例
char *ptr;
ptr = (char *)malloc(sizeof(char)*9);
釋放記憶體函式- free( )
標頭檔: #include <stdlib.h>
#include <malloc.h>
語法:void free(void *ptr);
功能:釋放記憶體
範例:Free(ptr);