14
第第第 第第 8-1 第第 8-2 第第第第第第第 8-3 第第第第

第八章 指標

  • Upload
    hertz

  • View
    39

  • Download
    0

Embed Size (px)

DESCRIPTION

第八章 指標. 8-1 指標 8-2 動態變數與陣列 8-3 綜合範例. 第八章 指標. 截至目前為止,我們介紹的資料型別有 2-3 節基本資料型別、第七章的陣列型別及結構型別,本章 8-1 節將介紹另一個進階資料型別,稱為指標 (Pointer) 。筆者也將在 8-2 節中說明如何使用指標及 malloc( ) 函式,以便在執行階段動態的配置記憶體。. 8-1 指標. 指標型別是所有高階語言所沒有的資料型別,它的優點是指標型別直接 與記憶體打交道,如此可以提升程式的執行效率。 指標型別的宣告 - PowerPoint PPT Presentation

Citation preview

Page 1: 第八章   指標

第八章 指標

•8-1 指標•8-2 動態變數與陣列•8-3 綜合範例

Page 2: 第八章   指標

第八章 指標

截至目前為止,我們介紹的資料型別有 2-3節基本資料型別、第七章的陣列型別及結構型別,本章 8-1 節將介紹另一個進階資料型別,稱為指標 (Pointer) 。筆者也將在 8-2 節中說明如何使用指標及 malloc( ) 函式,以便在執行階段動態的配置記憶體。

Page 3: 第八章   指標

8-1 指標指標型別是所有高階語言所沒有的資料型別,它的優點是指標型別直接與記憶體打交道,如此可以提升程式的執行效率。

指標型別的宣告指標型別的宣告比較特殊,它必須藉助一種指標運算子( * ),其宣告

語法如下:

資料型別  * 指標變數;

資料型別可以是 3-2 節的基本資料型別,指標變數可以是一個合法的變數

名稱。例如,以下式子即宣告 ptr 是一個整數的指標變數。

int *ptr ;

經過以上宣告之後, ptr 即可指向任一整數變數位址,例如,

int a=5 ;prt = &a;

Page 4: 第八章   指標

則 ptr 指向整數 a 的位址,往後即可使用 *ptr 代表整數 a 。例如,以下敘述

可印出 *ptr 的值。

printf (“%d”, *ptr) ;

若硬要印出 ptr 的值,如以下敘述:

printf (“%d”, ptr) ;

則沒有意義了。因為 ptr 的值會隨著不同的機器與不同的執行次數而有不同的值。所以,在指標型別中,我們並不在意 ptr 所在位址,在意的是 *ptr的值。

Page 5: 第八章   指標

指標與一維陣列

接著我們要談如何使用指標型別存取陣列的值。例如,程式中若包含以下的宣告:

int *ptr;int a[5]={3, 8, 6, 2, 5};ptr = a;     或 ptr = &a[0];

則表示宣告 ptr 是一種指標型別, ptr 本身是一個位址, *ptr 才是一個值,其中 ptr=a 的效果就是將 ptr 指向 a[0] 的位址, & 符號是取址的意思。

所以若經以上設定,

printf(“%d”, *ptr);

將可得 3 ,若要得下一個陣列值,則應將指標向後移一個位置,例如:ptr++; /* ptr=ptr+1 */printf(“%d”, *ptr); 或 printf(“%d”, ptr[1]);

均可得到結果 8 。其次,上式若只純粹取值,亦可以下式表示:printf(“%d”, *(ptr+1));

Page 6: 第八章   指標

範例 8-1a同範例 7-1c, 但改用指標型別處理陣列的值。

範例 8-1b請以指標型別重做泡沫排序法。

Page 7: 第八章   指標

指標與二維陣列二維陣列在人們眼中通常用於處理二維的行列表格,但電腦內部的記憶體中,是以一維的方式排列,所以雖然是二維的陣列,但在電腦記憶體中已轉為一維的方式儲存,二維陣列以指標處理的步驟是先指定第一元素給指標變數,如下所示:

int *ptr, a[4][3];ptr = &a[0][0]; /* 不能寫成 ptr=a */

其次,若要存取其值,只要使用陣列名稱與適當的位移即可。例如,以下敘述可設定第i列第 j 行元素等於 5 。

*( *(a+i ) + j) =5; /* 不能寫成 * ( *ptr+i ) + j = 5 */

上式若要以 ptr 表示,則應使用以下敘述將二維排列轉為一維的直線列,其中 3 是第一維的行個數。

*( ptr + 3*i + j ) =5; /* 不能寫成 * ( a + 3*i + j ) = 5 */

Page 8: 第八章   指標

以上敘述將二維的列與行轉為一維的直線排列,如下表所示,括號內為二維(列、行),括號外的為一維直線的位移量。

範例 8-1c請以指標重做範例 7-1g 的學生成績統計。

a(0,0)

0

A(0,1)

1

A(0,2)

2

A(1,0)

3

A(1,1)

4

A(1,2)

5

A(2,0)

6

A(2,1)

7

A(2,2)

8

A(3,0)

9

A(3,1)

10

A(3,2)

11

Page 9: 第八章   指標

變數與陣列除了可於設計階段佈置外,亦可於執行階段再產生,於設計階段所佈置好的變數或陣列稱為靜態變數或陣列;於執行階段產生的,則稱為動態變數或陣列。為什麼要有動態變數或陣列呢 ? 那是因為有些

情況,於程式設計階段,並不知道要預留多大的陣列,若不管使用者所需要的陣列大小為何,通通宣告一個最大值,則非常浪費記憶體,此時即可使用本節所要介紹的動態變數與陣列。本節將介紹如何利用指標及簡單的 malloc( ) 函式,動態的取得程式執行時所需的記憶體。

• 動態變數及陣列使用步驟有三:宣告變數及陣列、動態產生變數及陣列、以及動態變數及陣列的存取,最後是釋放動態記憶體。分別說明如下:

8-2  動態變數與陣列

Page 10: 第八章   指標

宣告變數及陣列變數動態陣列變數的宣告同一般陣列,如以下敘述可宣告一個 edi 變數,其

型別為 int 。

int * edi;

以下敘述,可宣告一個 edi 變數,其型別為 pData 。pData * edi;

pData 型別定義如下:struct pData{ char *name; int age;};

以下敘述可宣告一個 edi 陣列變數,其型別為 pData 。pData * edi[2];

以下敘述可宣告一個 edi 的二維陣列,其型別為 pData 。pData * edi[3][2];

Page 11: 第八章   指標

動態產生變數及陣列使用標頭檔< stdlib.h>中已宣告的 malloc( ) 函式及 free( ) 函式,於程式

執行時直接向記憶體要空間及釋放空間。

如果陣列有 100 個 int ,我們就必須明白的告訴記憶體 100 個 int需要多少個

bytes ,如下列程式片段所示:

edi = malloc ( n * sizeof(int) ); /* n=100 */

釋放記憶體由於動態陣列是在程式執行時,直接向記憶體要求取得的,因此在程式結束前,必須釋放出所取得的記憶體,如下所示。

free (edi);

存取動態陣列動態陣列的使用與上節所介紹的指標存取相同,值得注意的是,動態向記憶體要求取得的記憶體時並沒有進行初始化的動作,所配置到的記憶體預設值不一定為 0 ,因此在使用動態陣列時,要特別注意初始值的設定。

Page 12: 第八章   指標

範例 8-2a示範動態變數的用法。

範例 8-2b示範動態陣列的使用。本例於設計階段並不知使用者所要輸入的個數,所以採用動態陣列逐一配置記憶體。

範例 8-2c示範動態一維陣列的產生及資料的存取。

範例 8-2d示範動態二維陣列的產生。

範例 8-2e示範兩個矩陣相加。

Page 13: 第八章   指標

8-3 綜合範例矩陣相乘若有矩陣 A23 如下,我們稱為 2 列 3 行、記為 A23 ,其中共有 6 個元素,每個元素編號如下:  

A23 = a11 a12 a13 a21 a22 a23

矩陣要能進行相乘,必須第一個矩陣的行數等於第二個矩陣的列數,且相乘結果的列數要等於第一個矩陣的列數;結果的行數等於第二個矩陣的行數。如下式為 A矩陣乘以 B矩陣的行列數目表示法。 Anm × Bmp = Cnp

其次,若有矩陣如下 :Cnp = Anm × Bmp

則任一子集合 Cnp 如下: m

Cnp = Ank × Bkp k=1

Page 14: 第八章   指標

範例 8-3示範矩陣相乘。