1 第 6 章 指標 6-1 指標簡介 6-2 指標與陣列 6-3 動態配置記憶體 6-4...

48
1 第6第 第第 6-1 指指指指 6-2 指指指指指 6-3 指指指指指指6-4 指指指指指指

Post on 18-Dec-2015

233 views

Category:

Documents


2 download

TRANSCRIPT

1

第 6章 指標

6-1 指標簡介 6-2 指標與陣列6-3 動態配置記憶體6-4 本章綜合練習

2

6-1 指標簡介

了解變數所在記憶體位址,可以透過 &(取址運算子)來求出變數所在的位址,語法格式如下: & 變數名稱;

3

& 取址運算子的應用與實作: CH06_1

程式範例是學習指標觀念的入門磚,也就是透過 & 取址運算子來說明變數名稱、變數值與記憶體位址間的相互關係。

4

宣告指標變數

指標變數,就是一種用來儲存記憶體位址的變數,當指標變數指到目標位址後,可以透過程式移動指標 ( 包括將指標變數值做數值運算 ) ,即可取得該位址所代表記憶區塊的資料值。

指標變數宣告方式如下: 資料型態 * 指標名稱 ;   /* 第一種宣告方式 */

5

指標屬於系統低階的存取功能

透過指標可以存取記憶體中所指到的記憶區塊內容。

賦予指標錯誤的位址,而該位址又剛好為系統資料儲存的記憶區塊,此時若覆寫 (override) 該區塊內容,很可能造成系統不穩定或是當機的情形。

6

指標變數的宣告與相關示範: CH06_2

程式範例是說明整數與雙精度實數指標變數的位址、資料內容及指標變數所佔用的記憶體空間等相關內容,對指標既期待又怕受傷害的朋友,要好好研究這個範例喔!

7

指標變數與指定運算 (=) 的相關示範: CH06_3

程式範例是說明兩個指標變數指向同一位址的指定運算 (=) 與相關資料內容間的變化。

重新設定指標變數的資料內容後,指向同一位址的變數內容也會隨之改變。

8

指標運算

對於一般變數而言,當使用 + 運算子或 - 運算子來進行運算時,只會做變數本身數值的增減變化。

指標變數雖然是一種用來儲存位址值的變數,也可以針對指標使用 + 運算子或 - 運算子來進行運算,不過運算結果與一般變數就大不相同了。

9

指標變數示意圖

10

指標的加法與減法運算實作: CH06_4

程式範例是整數與雙精度實數指標變數加法與減法運算的示範與說明,並請仔細觀察各種運算後的位址變化。

11

多重指標

「指標的指標」( pointer of pointer ),就是「指向指標變數的指標變數」來儲存指標所使用到的記憶體位址與存取變數的值,或者可稱為「多重指標」。

12

多重指標示意圖

13

雙重指標的說明與相關示範: CH06_5

程式範例相當簡單,主要是說明雙重指標的宣告與使用,觀念就在表示除了 ptr1 是指向 num 的位址,則 *ptr1=10 。

ptr2 是指向 ptr1 的位址,因此 *ptr2=ptr1 ,而經過兩次「反參考運算子」的運算後,得到 **ptr2=10 。

14

三重指標的說明與相關示範: CH06_6

這個範例則是宣告了三重指標的應用與實作方式,依據相同的方法,您也可以自行練習宣告更多重的指標。

15

指標與陣列

「陣列名稱」就是指向陣列中第一個元素的記憶體位址,也可以代表該陣列在記憶體中的起始位址。

「索引值」其實就是其它元素相對於第一個元素的記憶體位址之「位移量」( offset )。

16

陣列與指標常數的運算說明與示範: CH06_7

程式範例是說明陣列與指標常數間的替代運算,並示範以兩種指標方式來存取陣列內的元素值。

在使用指標常數表示法時,陣列名稱上加 1 表示位移一個記憶體單位,而這個位移量與所宣告的資料型態有關。

17

不同資料型態陣列與位移量說明與示範:CH06_8

程式範例顯示宣告不同資料型態的陣列,與在陣列指標常數上進行加法運算後的位址位移量變化,這個位移量跟陣列資料型態所佔的位元組有關。

18

指標與一維陣列

指標變數可以藉由儲存變數位址,間接存取該變數的值。

在撰寫程式碼時,當然也可以將指標變數指到陣列的起始位址,並藉由反參考運算子「 * 」來存取陣列中的元素值。

19

指標變數與一維陣列的運算說明與示範:CH06_9

程式範例中已經定義好 iArrVal 陣列,並宣告一個指標變數來指向該陣列第一個元素的位址,另外透過反參考運算子「 * 」來間接存取陣列內的元素值。

20

指標與多維陣列

記憶體是線性構造,因此例如二維陣列,其於記憶體中也是以線性方式配置陣列的可用空間,當然二維陣列的名稱同樣也可以代表第一個元素的記憶體位址。

二維陣列具有兩個索引值,表示二維陣列利用兩個值來控制指定元素相對於第一個元素位移量,為了方便筆者說明,請看以下這個宣告: int arr[3][5];

21

元素記憶體示意圖

22

二維陣列的雙重指標表示法說明: CH06_10

程式範例是直接示範二維陣列與雙重指標間的應用,並實作雙重指標來列印二維陣列中的元素值。

23

指標常數

二維陣列是佔用連續記憶體空間,當然也可藉由指標變數指向二維陣列的起始位址來取得陣列的所有元素值。宣告方式如下: 資料型態 指標變數 =& 二維陣列名稱 [0][0]; /* 二

維陣列名稱須為已定義且資料型態與宣告指標變數相同的陣列。 */

24

記憶體中的排列方式

25

二維陣列矩陣相加

26

指標變數與矩陣加法的實作說明: CH06_11

程式範例,對於 A 、 B 、 C 二維陣列中的各元素,都將以指標變數的方式來存取。

27

指標與字串

字串其實是由字元陣列組成,不過須要在字元陣列的後面加上空字元‘ \0’ 。

字串也可以經由指標來宣告與操作。例如在 C 程式中可以利用字串指標變數來指向字串常數,宣告格式如下: char * 指標變數 ="字串內容 ";

28

變數的起始位置

29

字元陣列或指標宣告字串的說明與示範:CH06_12

程式範例分別示範字元陣列或指標宣告字串的方式,並進行字串指標的加法運算。

最大的重點是 Name 為指標常數 , 不可改變其值,而 p_N 指標變數 , 可改變其值。

30

指標陣列

指標陣列中的元素都是一個指標變數,而元素值則為指向其它變數的位址值。

J u s t i n i a n \0

M o m o \0 \0 \0 \0 \0 \0

B e c k y \0 \0 \0 \0 \0

B u s h \0 \0 \0 \0 \0 \0

31

二維字元陣列儲存方式說明與示範: CH06_13

程式範例就是二維字元陣列宣告與使用,各位可以利用此程式來觀察上圖的詳細資料配置方式,其中如果陣列元素是空字元則列印出 0 。

32

字串的記憶體圖

33

指標陣列與字串陣列儲存字串的說明與示範: CH06_14

程式範例是示範使用一維指標陣列與二維字串陣列來儲存字串的不同,這也是很經典的程式,特別是兩者所佔位址的不同,希望各位仔細研究!

34

動態配置記憶體

方式與比較項目 動態配置 靜態配置記憶體配置 執行階段。 編譯階段。記憶體釋放 程式結束前必需釋放配置的空

間,否則造成記憶體缺口。不需釋放,程式結束時自動歸還系統。

程式執行效能 較慢。 (因為所需記憶體必需於程式執行時才能配置 )

較快。 (程式編譯階段即已決定記憶體所需容量 )

指標遺失配置位址 若指向動態配置空間的指標,在未釋放該位址空間前,又指向別的記憶體空間時,則原本所指向的空間將無法被釋放,而造成記憶體缺口。

沒有此問題。

35

動態配置變數

配置變數的方式,也就是在執行階段時,依照資料型態來動態配置一個記憶體空間,並將配置空間位址傳回指派的指標變數。

這個資料型態範圍除了 C 的基本資料型態外,也可以包括如結構 (structure) 等自訂資料型態: 資料型態 * 指標名稱 =( 資料型態 *)malloc(sizeo

f( 資料型態 ));

36

動態配置記憶體示意圖

37

動態配置一般變數的說明與示範: CH06_15

程式範例是動態配置一個整數記憶體空間並輸入該整數數值,再列印出所指向的記憶體位址。

最後利用 free()函數釋放空間及列印出所指向的位址與內容。

38

動態配置陣列

動態配置陣列方式與動態配置變數相當類似,宣告後會在記憶體中自動尋找適合的連續記憶體空間,其長度須與指定資料型態再乘以陣列長度相符。

配置完成後,再將該記憶體區段的起始位址,傳回等號左邊所宣告的指標變數。

39

動態配置一維陣列的說明與示範: CH06_16

程式範例將由使用者輸入此一維動態配置陣列的大小,並利用亂數函數 rand()來設定值,最後再分別以陣列或指標方式來列印出動態陣列元素的值。

40

配置多維陣列

是從第一維開始,所配置的記憶體都是用來記錄下一維的陣列起始位址,只有最後一維才是真正儲存所指定資料內容的記憶體空間,若釋放時由第一維開始釋放,這樣將失去指向下一維的指標變數 ( 記憶體位址 ) 。

在釋放記憶體時必須將順序反過來,也就是由第 n 維逐步釋放至第一維。

41

動態配置二維陣列的說明與示範: CH06_17

程式範例,可以任意輸入學生個數及成績科數多寡,是一種典型動態動態配置與釋放二維陣列記憶體的實作,這也是個創意級的程式!

42

記憶體配置示意圖

43

二維陣列各維不同長度的動態配置說明與示範: CH06_18

44

雙重指標的應用的說明與示範: CH06_19

45

動態配置各維不同長度的二維陣列的說明與示範: CH06_20

試著將原來存放在陣列中的 4 個字串,動態配置各維不同長度的二維陣列,並分別配置第一維所對應的第二維長度來儲存字串,並計算出每個字串真正所佔用的位元組。

46

矩陣相乘的運算說明與示範: CH06_21

利用動態配置陣列方式輸入與儲存 A 、B矩陣元素,並求出 A 、 B矩陣相乘的結果。

47

轉置矩陣示意圖

48

轉置矩陣的運算說明與示範: CH06_22

設計一程式讓使用者動態配置陣列來輸入矩陣內容,並求取其轉置矩陣。