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
第八章 指標
•8-1 指標•8-2 動態變數與陣列•8-3 綜合範例
第八章 指標
截至目前為止,我們介紹的資料型別有 2-3節基本資料型別、第七章的陣列型別及結構型別,本章 8-1 節將介紹另一個進階資料型別,稱為指標 (Pointer) 。筆者也將在 8-2 節中說明如何使用指標及 malloc( ) 函式,以便在執行階段動態的配置記憶體。
8-1 指標指標型別是所有高階語言所沒有的資料型別,它的優點是指標型別直接與記憶體打交道,如此可以提升程式的執行效率。
指標型別的宣告指標型別的宣告比較特殊,它必須藉助一種指標運算子( * ),其宣告
語法如下:
資料型別 * 指標變數;
資料型別可以是 3-2 節的基本資料型別,指標變數可以是一個合法的變數
名稱。例如,以下式子即宣告 ptr 是一個整數的指標變數。
int *ptr ;
經過以上宣告之後, ptr 即可指向任一整數變數位址,例如,
int a=5 ;prt = &a;
則 ptr 指向整數 a 的位址,往後即可使用 *ptr 代表整數 a 。例如,以下敘述
可印出 *ptr 的值。
printf (“%d”, *ptr) ;
若硬要印出 ptr 的值,如以下敘述:
printf (“%d”, ptr) ;
則沒有意義了。因為 ptr 的值會隨著不同的機器與不同的執行次數而有不同的值。所以,在指標型別中,我們並不在意 ptr 所在位址,在意的是 *ptr的值。
指標與一維陣列
接著我們要談如何使用指標型別存取陣列的值。例如,程式中若包含以下的宣告:
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));
範例 8-1a同範例 7-1c, 但改用指標型別處理陣列的值。
範例 8-1b請以指標型別重做泡沫排序法。
指標與二維陣列二維陣列在人們眼中通常用於處理二維的行列表格,但電腦內部的記憶體中,是以一維的方式排列,所以雖然是二維的陣列,但在電腦記憶體中已轉為一維的方式儲存,二維陣列以指標處理的步驟是先指定第一元素給指標變數,如下所示:
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 */
以上敘述將二維的列與行轉為一維的直線排列,如下表所示,括號內為二維(列、行),括號外的為一維直線的位移量。
範例 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
變數與陣列除了可於設計階段佈置外,亦可於執行階段再產生,於設計階段所佈置好的變數或陣列稱為靜態變數或陣列;於執行階段產生的,則稱為動態變數或陣列。為什麼要有動態變數或陣列呢 ? 那是因為有些
情況,於程式設計階段,並不知道要預留多大的陣列,若不管使用者所需要的陣列大小為何,通通宣告一個最大值,則非常浪費記憶體,此時即可使用本節所要介紹的動態變數與陣列。本節將介紹如何利用指標及簡單的 malloc( ) 函式,動態的取得程式執行時所需的記憶體。
• 動態變數及陣列使用步驟有三:宣告變數及陣列、動態產生變數及陣列、以及動態變數及陣列的存取,最後是釋放動態記憶體。分別說明如下:
8-2 動態變數與陣列
宣告變數及陣列變數動態陣列變數的宣告同一般陣列,如以下敘述可宣告一個 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];
動態產生變數及陣列使用標頭檔< stdlib.h>中已宣告的 malloc( ) 函式及 free( ) 函式,於程式
執行時直接向記憶體要空間及釋放空間。
如果陣列有 100 個 int ,我們就必須明白的告訴記憶體 100 個 int需要多少個
bytes ,如下列程式片段所示:
edi = malloc ( n * sizeof(int) ); /* n=100 */
釋放記憶體由於動態陣列是在程式執行時,直接向記憶體要求取得的,因此在程式結束前,必須釋放出所取得的記憶體,如下所示。
free (edi);
存取動態陣列動態陣列的使用與上節所介紹的指標存取相同,值得注意的是,動態向記憶體要求取得的記憶體時並沒有進行初始化的動作,所配置到的記憶體預設值不一定為 0 ,因此在使用動態陣列時,要特別注意初始值的設定。
範例 8-2a示範動態變數的用法。
範例 8-2b示範動態陣列的使用。本例於設計階段並不知使用者所要輸入的個數,所以採用動態陣列逐一配置記憶體。
範例 8-2c示範動態一維陣列的產生及資料的存取。
範例 8-2d示範動態二維陣列的產生。
範例 8-2e示範兩個矩陣相加。
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
範例 8-3示範矩陣相乘。