【C++ 筆記】指標(Pointer)(下) - part 13 === 目錄(Table of Contents): [TOC] --- 很感謝你點進來這篇文章。 你好,我並不是什麼 C++、程式語言的專家,所以本文若有些錯誤麻煩請各位鞭大力一點,我極需各位的指正及指導!!本系列文章的性質主要以詼諧的口吻,一派輕鬆的態度自學程式語言,如果你喜歡,麻煩留言說聲文章讚讚吧! 指標與陣列(Pointer vs. Array) --- 指標與陣列其實是有相關性的,先從定義上來看: :::success 陣列的定義: 陣列是一組相同型態的元素,這些元素在記憶體中是連續儲存的。陣列的名稱可以視為指向其首項元素的指標。例如,對於一個整數陣列 int arr[5];,arr 實際上是指向 arr 的指標。 ::: :::info 指標的定義: 指標是一種變數,用來儲存其他變數的位址。指標可以指向任何型態的資料,包括陣列。 ::: > 指標和陣列在很多情況下是可以互換的。例如,一個指向陣列開頭的指標,可以透過使用指標的算術運算或陣列索引來存取陣列。請看下面的程式: ```cpp= #include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; int *ptr; // 指標中的陣列位址 ptr = var; for (int i = 0; i < MAX; i++) { cout << "var[" << i << "] 的記憶體位址為 "; cout << ptr << endl; cout << "var[" << i << "] 的值為 "; cout << *ptr << endl; // 移動到下一個位置(索引) ptr++; } return 0; } ``` 輸出結果: ``` var[0] 的記憶體位址為 0x61fe08 var[0] 的值為 10 var[1] 的記憶體位址為 0x61fe0c var[1] 的值為 100 var[2] 的記憶體位址為 0x61fe10 var[2] 的值為 200 ``` 來源:https://www.runoob.com/cplusplus/cpp-pointers-vs-arrays.html 以上範例即將指標遞增,具有與 i 相同的功能,能夠遍歷整個陣列。 > 然而,指標和陣列並不是完全互換的。例如,請看下面的程式: ```cpp= #include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; for (int i = 0; i < MAX; i++) { *var = i; // 這是正確的語法 var++; // 這是不正確的 } return 0; } ``` > 把提取(Dereference)運算子 `*` 應用到 `var` 是完全可以的,但修改 `var` 的值是非法的。這是因為 var 是指向陣列開頭的**常數**,不能作為左值(lvalue)。 :::success 左值(lvalue)和右值(rvalue): ```cpp= int x = 0; ``` 右值為 `0`,(專業術語為:literal constant -> 字面常數),而變數 `x` 為左值。 左值(lvalue):任何有記憶體位址的變數都是左值,包括不可修改的 const 變數。 右值(rvalue):非左值即右值,通常也是運算式所產生暫時的值。 ::: > 由於一個陣列名稱對應一個指標常數,只要不改變陣列的值,仍然可以用指標形式的運算式。例如,下面是一個有效的語句,把 var[2] 賦值為 500: ```cpp= *(var + 2) = 500; ``` 指標型陣列(Array of Pointers) --- 以下是指標陣列的宣告方式: ```cpp= int *ptr[MAX]; ``` 以上是一個指標陣列,長度共有 MAX 個,裡面所有的元素皆指向整數型態。 你可能會很疑惑,為何還需要指標陣列呢?原因是他有以下這五大優點: 1. 靈活的記憶體管理 2. 簡化多維資料結構的處理 3. 提升效能 4. 簡化函數參數傳遞 5. 實現複雜資料結構 以下是一個範例: ```cpp= #include <iostream> using namespace std; int main() { // 定義一個整數陣列 int numbers[] = {10, 20, 30, 40, 50}; // 計算陣列的大小 int size = sizeof(numbers) / sizeof(numbers[0]); // 定義一個指標陣列,指向整數 int* pointers[size]; // 將每個指標指向整數陣列中的元素 for (int i = 0; i < size; ++i) { pointers[i] = &numbers[i]; } // 輸出每個指標所指向的值 cout << "Values in the array using pointer array:" << endl; for (int i = 0; i < size; ++i) { cout << "Value at pointers[" << i << "] = " << *pointers[i] << endl; } return 0; } ``` 輸出結果: ``` Values in the array using pointer array: Value at pointers[0] = 10 Value at pointers[1] = 20 Value at pointers[2] = 30 Value at pointers[3] = 40 Value at pointers[4] = 50 ``` 以下是一個指向字元的指針陣列,用以儲存字串列表的範例: ```cpp= #include <iostream> using namespace std; const int MAX = 4; int main (){ const char *names[MAX] = { "C++ is best.", "I am handsome!", "Haha welcome to programming world.", "good night.", }; for (int i = 0; i < MAX; i++) { cout << "Value of names[" << i << "] = "; cout << names[i] << endl; } return 0; } ``` 輸出結果: ``` Value of names[0] = C++ is best. Value of names[1] = I am handsome! Value of names[2] = Haha welcome to programming world. Value of names[3] = good night. ``` 雙重指標(Pointer to Pointer / Double Pointer) --- 我們都知道指標是一個變數,用於儲存另一個變數的記憶體位址。 那麼雙重指標就是一個指標指向另一個指標,那麼所儲存的也就是指標的記憶體位址。 語法是加上兩個星號,如下: ```cpp= int **var; ``` 以下是一個範例: ```cpp= int value = 100; int *ptr = &value; // 單層指標,指向整數值 int **doublePtr = &ptr; // 雙層指標,指向單層指標 ``` 那他有什麼用呢?請看以下三點: 1. 動態記憶體管理:雙重指標常用於動態分配二維陣列或其他複雜資料結構。由於需要管理多個指標,使用雙重指標可以方便地處理記憶體分配和釋放。 2. 函數參數傳遞:當需要在函數中修改指標本身時,雙重指標非常有用。使其可在函數內部改變傳入的指標,指向新的記憶體位址。 3. 處理複雜資料結構:雙重指標也適用於處理更複雜的資料結構,如鏈結串列、二元樹等。在這些結構中,常需要透過多層的 Dereference 來存取或修改節點。 再來練習一題!以下是一個範例: ```cpp= #include <iostream> using namespace std; int main () { int var; int *ptr; int **pptr; var = 3000; // 獲取 var 的地址 ptr = &var; // 使用運算子 & 獲取 ptr 的地址 pptr = &ptr; // 使用 pptr 獲取值 cout << "var 值為 : " << var << endl; cout << "*ptr 值為 : " << *ptr << endl; cout << "**pptr 值為 : " << **pptr << endl; return 0; } ``` 輸出結果: ``` var 值為 : 3000 *ptr 值為 : 3000 **pptr 值為 : 3000 ``` 函數回傳指標 --- 語法: ```cpp= int * myFunction() { . . . } ``` 此函數即表為可以回傳指標的函數。 > ***另外,C++ 不支援函數外回傳局域變數的位址,除非定義局域變數為 static 變數。*** 以下是一個範例: ```cpp= #include <iostream> using namespace std; // 函數回傳一個指向整數的指標 int* createNumber() { static int number = 42; return &number; } int main() { int* numberPtr = createNumber(); // 取得 createNumber() 之回傳值 // 使用回傳的指標 cout << "The number is: " << *numberPtr << endl; return 0; } ``` 輸出結果: ``` The number is: 42 ``` 總結 --- 指標與陣列息息相關,可透過指標對陣列做出一些運算。最常見就是拿指標遍歷一個陣列。 以下是指標陣列的宣告方式:`int *ptr[MAX];` 雙重指標即加上兩顆星星:`int **var;` C++中可以在函數裡面回傳指標。 以上,結束。 參考資料 --- [C++ Pointer To Pointer (Double Pointer) - GeeksforGeeks](https://www.geeksforgeeks.org/cpp-pointer-to-pointer-double-pointer/) [C/C++ 中的雙指標](https://codelove.tw/@tony/post/8xXwAq) [指標的指標](https://openhome.cc/Gossip/CGossip/Pointer2Pointer.html) [C++ 左值與右值 - HackMD](https://hackmd.io/@23657689/cpp_lvalue_rvalue) [C++ 指针 vs 数组 | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-pointers-vs-arrays.html) [C++ 指针数组 | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-array-of-pointers.html) [C++ 指向指针的指针(多级间接寻址) | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-pointer-to-pointer.html) [C++ 从函数返回指针 | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-return-pointer-from-functions.html)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.