Chapter 7 指標
簡介 間接 模仿傳名呼叫 指令行參數 變數堆
指標 指標就像一個整數,固定一個數值 必須被宣告以它伴生的型: 常用於: 解釋為對象地址 “整數指標”, “浮點數指標”, 之類的 動態物件 (存放在 heap) 直接存取記憶體位址 (或是對應記憶體)
間接指標 藉由指標存取一個物件稱之間接 "address-of" 運算元 (&) 獲得對象的地址 "de-referencing“ 運算元 (*) 獲得對象的參考
Indirection Example #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i = 9, * ip = &i; printf("Address %p is %d\n", ip, *ip); *ip = 10; system("pause"); return 0; }/* Address 0012FF7C is 9 Address 0012FF7C is 10 */
Pointer Diagram
參考語意 當參數傳遞的時候可以參考語意 C 不支援直接存取 在C中 我們使用指標模擬 改變傳入的參數,原始參數也會變動 Java 並不支援
Simulating Reference Semantics #include <stdio.h> #include <stdlib.h> void swap(int* x, int* y) { int temp = *x; *x = *y; *y = temp; } int main(int argc, char *argv[]) { int i = 1, j = 2; swap(&i, &j); printf("i == %d, j == %d\n", i, j); system("pause"); return 0; // i == 2, j == 1
Ragged Arrays
命令行參數 通常使用在main程式中 argv 是 ragged array int main( int argc, char* argv[]) { … } argv 是 ragged array
Command-line Arguments #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; ++i) printf("%s",argv[i]); system("pause"); return 0; } /* D:\>test hello there D:\test.exe hello there */
NULL 指標 一個特殊的值 並沒有指向任何地方 可以用來比較其他指標 e.g., 作為基礎 不能間接引用 NULL 位址是零 可以回傳指定的函式庫函數 不能間接引用 NULL
變數堆 間接地獲取藉由指標 居住在一個獨特的資料區 當要釋放變數時候 對於不知道要用多少變數而言是方便的 由 malloc() 函數達成 通常叫 "heap" or "dynamic storage" 當要釋放變數時候 藉由 free() 函數達成 對於不知道要用多少變數而言是方便的 就像一個你想多大就多大的陣列
C Heap Functions Defined in <stdlib.h>: void *malloc(size_t size); void free(void *memblock); void *calloc(size_t num, size_t size); void *realloc(void *memblock, size_t size);
Example #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXWIDTH 81 #define MAXLINES 100 int main(int argc, char *argv[]) { char* lines[MAXLINES]; char line[MAXWIDTH]; int i, n; for (n = 0; n < MAXLINES && gets(line) != NULL; ++n) { if ((lines[n] = (char *)malloc(strlen(line) + 1)) == NULL) exit(1); strcpy(lines[n], line); }/* Print in reverse order */ for (i = 0; i < n; ++i) { printf("%s\n",lines[n-i-1]); free(lines[n-i-1]); } system("pause"); return 0;
sizeof 運算子 傳回變數佔用的大小 是一個翻譯器運算子 計算陣列大小: int n = sizeof a / sizeof a[0]; 對於型態需要使用括號: float* p = malloc( sizeof( float));
Heap 中的 structs 使用 sizeof, 用法: struct Employee* p = malloc( sizeof( struct Employee)); 存取成員的方法: (*p).age = 47; 另一種方法 ( -> 運算子): p->age = 47;
structs as Arguments 通常會傳 struct 的位址 輸入指標參數 省去時間和空間
Example #include <stdio.h> #include <stdlib.h> struct Date { int year, month, day; }; void printDate(struct Date* p) { printf("%2d/%2d/%02d\n", p->month, p->day, p->year); } int main(int argc, char *argv[]) { struct Date d = { 98, 10, 2 }; printDate(&d); system("pause"); return 0; } // 10/ 2/98
Arrays as Arguments 傳遞整個陣列是沒有效率的 指標僅傳遞元素的位址 char* 及 char[] 代表相同的參數傳遞法 *argv[] 同義於 **argv