• 沒有找到結果。

指標

N/A
N/A
Protected

Academic year: 2022

Share "指標"

Copied!
41
0
0

加載中.... (立即查看全文)

全文

(1)

C 程式設計—

指標

(2)

課程大綱

„ C語言簡介

„ 基本資料型態, 變數, 基本輸入輸出

„ 控制敘述- 選擇控制與重覆控制

„ 陣列

„ 函式

„ 指標

„ 字元與字串

„ 結構

„ 檔案處理

(3)

本次上課大綱

„ 指標與記憶體位址

„ 指標運算

„ 函式的傳指標呼叫

„ 指標和陣列

„ 指標與函式

„ 多重指標

„ main函式的引數串列與回傳值

„ 動態記憶體配置

(4)

什麼是指標( pointer)

„ 指標

‰

一種變數

‰

儲存記憶體位置

‰

儲存在該記憶體中的可能是字元, 整數,指標本身變 數的位置

‰

程式可以間接取得該指標所指位址的變數值

„ 指標

‰

節省記憶體空間

‰

減少不必要的搬動

‰

使用不當的話, 造成系統或程式嚴重的錯誤

(5)

存取記憶體內容

(6)

宣告指標變數 (1)

„ 指標的宣告方式與變數的宣告方式相同, 只不 過指標在變數前面多加一個 *

„ 資料型態 *指標變數名稱

‰

int *int_ptr;

‰

char *ch_ptr;

‰

float *float_ptr;

‰

double *double_ptr;

(7)

宣告指標變數 (2)

int i=3;

int *ptr;

ptr=&i;

1012

3 1000

1004

1008 1012

ptr是一個指向整數型 態的指標, 內容為該整 數的位址

i是一個整數, 內容為3, 與

*ptr的值一樣

記憶體位址

(8)

取址運算子與指標運算子 (1)

„ &是取址運算子

‰

用來取得該變數在記憶體的位址

‰

&變數名稱

int i=3;

int *ptr;

ptr=&i;

1012

3 1000

1004

1008 1012

記憶體位址 ptr是一個

整數指標

*ptr取得該指 標的內容值

&i取得該整數在記 憶體中 的位址

i是一個整數

(9)

取址運算子與指標運算子 (2)

„ *是指標運算子

‰

用來取得指標所指向位址的內容值

‰

*指標變數名稱

int i;

int *p;

p=&i;

*p=50

記憶體位址 記憶體位址

1012

50 1012

??

1000 1000 1004 1004

1008 1008

1012 1012

(10)

練習時間

„ 每一種資料型態的指標變數在32位元的作業系 統環境中都佔用4個bytes,因為指標變數存放 的是記憶體位址

„ 比較輸出指標的位址與值.

(11)

指標運算 (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

(12)

指標運算 (2)

„ 加減運算

‰

只能加常數值

‰

將指標變數內容『加1』

„ 依據指標指向的資料型態所佔用的記憶體單位大小,來決

定移動多少個位址(加1代表加1個單位),以便指向正確 的下一筆同樣資料類型的資料。

„

例子

int *p,*q;

p=p+q; /* 不合法 */

(13)

指標運算 (3)

„ 比較運算

‰

相同型態的指標變數可以做比較運算,藉由比較運 算,我們可以得知記憶體位址的先後關係

‰

較早配置記憶體的變數位於較高的記憶體位址

„ 例子

(14)

指標運算 (4)

„ 差值運算

‰

兩個相同資料型態的指標變數可以做減法運算

‰

代表兩個記憶體位址之間的可存放多少個該資料型 態的資料

‰

例子

(15)

傳址呼叫 (1)

„ 傳值呼叫

‰

call by value

„ 傳址呼叫

‰

call by address

(16)

1 /* 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.

(17)

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.

(18)

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.)

(19)

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

125 125

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.)

(20)

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.

(21)

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.

(22)

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.

(23)

練習時間

#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

(24)

傳址呼叫 (2)

傳值呼叫 傳址呼叫

(25)

指標與陣列

„

int array[10]; 我們以陣列名為array代表陣列的起 始位址, 以array+1表示下一個位址.

„

當宣告指標時, int *ptr; 則以ptr代表其位址, 以 ptr+1代表下一個位址.

„

陣列其實也是指標的一種應用.

(26)

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.

(27)

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.

(28)

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.

(29)

練習時間

„ 陣列其實也是指標的一種應用.

‰

如果用array++會怎樣?

„ 使用指標控制陣列.

‰

如果用ptr++會怎樣?

(30)

指標與二維陣列

„ 例子

int array[3][4], *ptr;

ptr=(int *)array;

array[1][2] 跟 ptr[3*1+2]的比較

(*(array+1))[1]跟*((array+1)[1])的比較

„ 多重指標與二維陣列

‰

例子

(31)

指標陣列

„ 陣列裡面所包含的元素都是指標.

„ 指標陣列型態

‰

int *int_ptr[10]; // 整數指標陣列

‰

float *float_ptr[10];

‰

double *double_ptr[10];

‰

char *str[10];

„ 例子:

(32)

指標與函數

„ 函數的名稱與陣列的名稱一樣, 都代表著起始 位址, 同時也是一個指標的常數, 因此函數指標 可做如下的宣告:

‰

void (*func)(void);

„ 例子:

‰

傳回整數的指標函數:

‰

如果把程式中第9行的 *func(i) 變成 func(i)的話, 會 怎樣?

(33)

指標的指標 (1)

„ int * ptr; /* 指標 */

„ int ** ptr; /* 指向指標的指標 */

„ int *** ptr; /* 三層指標變數 */

ptr *ptr **ptr

位址 位址 整數值

雙重指標

(34)

指標的指標 (2)

(35)

指標的指標 (3)

„

使用多重指標(指標的指標)將九九乘法表的乘法結 果儲存在9*9的二維整數陣列,並將陣列的資料列印出 來

陣列表示法 指標表示法

array[i][j] *(*(array+i)+j)

(36)

問題 :

„ 請問下列程式的執行結果

#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;

}

(37)

main()的argc與argv

„

定義方式一

‰ int main(int argc,char *argv[])

„

定義方式二:

‰ int main(int argc,char argv[][]) /* 使用二維字元陣列(字串陣列) */

„

定義方式三:

‰ int main(int argc,char **argv) /* 使用指標的指標 */

„

argc表示命令列中參數字串的個數.

„

argv表示指向命令列中所有參數字串的指標.

„

例子

(38)

動態記憶體配置

„ 使用在某些陣列大小無法於事先決定的情況

‰

C語言不能宣告一個陣列大小為變數的陣列

„ 需要用多少記憶體空間,就向系統要多少記憶 體空間

„ 於執行過程中配置一個適當大小的記憶體空間

給指標,接著藉由這個指標來存取分配到的記

憶體空間內的資料

(39)

配置記憶體函式- malloc( )

„ 標頭檔:

‰

#include <stdlib.h>

‰

#include <malloc.h>

„ 語法:void *malloc(size_t size);

„ 功能:動態配置記憶體

„ 範例

char *ptr;

ptr = (char *)malloc(sizeof(char)*9);

(40)

釋放記憶體函式- free( )

„

標頭檔:

‰ #include <stdlib.h>

‰ #include <malloc.h>

„

語法:void free(void *ptr);

„

功能:釋放記憶體

„

範例:

Free(ptr);

„

我們透過malloc函式取得的記憶體,可以於不需再使 用的狀況下,透過free函式將之歸還給系統

(41)

今天學到了什麼

„ 什麼是指標

„ 如何使用指標運算

„ 如何使用函式的傳指標呼叫

„ 如何使用指標和陣列

„ 如何使用指標與函式

„ 如何使用多重指標

„ 如何使用main函式的引數串列與回傳值

„ 如何使用動態記憶體配置

參考文獻

相關文件

Salas, Hille, Etgen Calculus: One and Several Variables Copyright 2007 © John Wiley &amp; Sons, Inc.. All

Salas, Hille, Etgen Calculus: One and Several Variables Copyright 2007 © John Wiley &amp; Sons, Inc.. All

Salas, Hille, Etgen Calculus: One and Several Variables Copyright 2007 © John Wiley &amp; Sons, Inc.. All

Salas, Hille, Etgen Calculus: One and Several Variables Copyright 2007 © John Wiley &amp; Sons, Inc.. All

Tense : simple present tense Phonics / Spelling : initial. sound, ending sound, letter

• To the right of the Draw mode buttons you find push buttons through which you can access all the functions that you need to define and solve the PDE problem: define

As with all poetry, is-poems are a little more complicated than it looks. You need to write down all your associations and ideas and then just select a few, adding the

1.1.3 In an effort to provide affordable and quality KG education to all eligible children, the Hong Kong Special Administrative Region Government (the Government)