對 “C語言指標變數作為函式引數” 的個人理解
此文為自己的一些理解和看法,如有錯誤,請各位大佬指出。
C指標
C中每個變數都有一個記憶體空間,每一個記憶體空間都有自己的地址,我們可以對變數使用 & 來獲取變數地址,如下所示:
//執行程式碼
#include<stdio.h>
int main() {
int num = 1;
float fnum = 2.1f;
char letter = 'a';
printf("num 的地址為 %p\n", &num);
printf("fnum 的地址為 %p\n", &fnum);
printf("letter 的地址為 %p\n", &letter);
return 0;
}
//執行結果
num 的地址為 000000CE34B6FB54
fnum 的地址為 000000CE34B6FB74
letter 的地址為 000000CE34B6FB94
何為指標
指標是一個變數,它的值為另一個變數的地址,即,記憶體空間的直接地址。我們在使用指標儲存其他變數地址之前,先進行宣告。
DataType *ptr;
//DataType為變數型別,ptr為指標名稱
int *iptr; /*整型指標*/
float *fptr; /*float型指標*/
char *cptr; /*字元型指標*/
所有資料型別對應指標的值的型別都是一樣的,都是一個代表記憶體地址的十六進位制數。
不同資料型別的指標之間唯一的不同是,指標所指向的變數或常量的資料型別不同。
指標的使用
建立一個指標iptr儲存num的地址。其中對指標使用星號*獲取指標指向的值。
#include<stdio.h>
int main() {
int num = 1;
int* iptr = #
printf("變數 num 的值為 %d\n", num);
printf("指標 iptr 所指向的值為 %d\n", *iptr);
printf("變數 num 的地址為 %p\n", &num);
printf("指標 iptr 所儲存的地址為 %p\n", iptr);
return 0;
}
變數 num 的值為 1
指標 iptr 所指向的值為 1
變數 num 的地址為 000000A1E514F594
指標 iptr 所儲存的地址為 000000A1E514F594
函式引數
當呼叫函式時,把實參的值複製給形參,然後函式用形參來進行相關操作。在函式內形參的值變化並不會影響實參的值變化。
#include<stdio.h>
void test(int num) {
printf("test中 num的值為%d 地址為%p\n", num, &num);
}
int main() {
int num = 1;
printf("main中 num的值為%d 地址為%p\n", num, &num);
test(num);
return 0;
}
main中 num的值為1 地址為000000D6EA4FFC24
test中 num的值為1 地址為000000D6EA4FFC00
可以看出當函式呼叫時,形參只是複製了實參的值,它們的記憶體地址是不一樣的。
所以當形參改變自己的值時,相應的實參是不會變化的。
#include<stdio.h>
void test(int num) {
printf("test中 num的值為%d 地址為%p\n", num, &num);
num = 2;
printf("test中 num的值為%d 地址為%p\n", num, &num);
}
int main() {
int num = 1;
printf("main中 num的值為%d 地址為%p\n", num, &num);
test(num);
printf("main中 num的值為%d 地址為%p\n", num, &num);
return 0;
}
main中 num的值為1 地址為000000062894FA04
test中 num的值為1 地址為000000062894F9E0
test中 num的值為2 地址為000000062894F9E0
main中 num的值為1 地址為000000062894FA04
test函式內改變num的值時,是對形參num操作,因此實參num的值仍為1。
指標作為函式引數
為何函式需要指標作為引數呢?
從上面可以看出,當我們想用test函式對main中的num值進行修改時,其實main中的num是沒有變化的。如果我們想要通過函式操作改變main中num值時,該怎麼操作呢?這就需要指標來進行相關的操作,從而實現我們的需求(ps:當然我們也可以通過return返回我們需要的值)。
為什麼通過指標能修改實參值
我們通過下面的一個例子來說明
#include<stdio.h>
void test(int *num_ptr) {
printf("test中 num_ptr儲存的地址為%p 所指向的值為%d\n", num_ptr, *num_ptr);
*num_ptr = 2;
printf("test中 num_ptr儲存的地址為%p 所指向的值為%d\n", num_ptr, *num_ptr);
}
int main() {
int num = 1;
printf("main中 num的地址為%p 值為%d\n", &num, num);
test(&num);
printf("main中 num的地址為%p 值為%d\n", &num, num);
return 0;
}
main中 num的地址為000000943AB2F6B4 值為1
test中 num_ptr儲存的地址為000000943AB2F6B4 所指向的值為1
test中 num_ptr儲存的地址為000000943AB2F6B4 所指向的值為2
main中 num的地址為000000943AB2F6B4 值為2
此時test的實參為num的地址,形參num_ptr複製的是num的地址。雖然在函式中對形參的值進行改變時,實參不會受到影響。但有趣的是,num_ptr的值是地址,當我們通過修改此指標指向的內容時,num_ptr還是儲存的是num的地址,num的地址沒有收到影響但num值已經改變。
舉個例子,把實參當一把鑰匙,形參當做另外配的鑰匙。
在函式內你重新改造形參鑰匙(即更改內容),實參鑰匙沒有影響。
如果這時候有一個房間,實參是房間的鑰匙(指標為鑰匙,指向的記憶體為房間),由於形參鑰匙與實參鑰匙一樣,故通過形參鑰匙可以修改房間的佈局(修改指向的記憶體內容)。當函式執行完後,形參鑰匙被丟棄,房間佈局已改變。
如果拿到形參鑰匙,對鑰匙進行改造,形參鑰匙就只能開另外一個房間。而原房間不受影響。
一句話
形參只是複製實參的值,形參如何變化不管實參的事。但形參通過指標修改指向的內容,就會影響實參所指向的內容,雖然此時形參和實參的值一樣。
相關文章
- C語言函式傳遞指標引數的問題詳解C語言函式指標
- C語言指標(二) 指標變數 ----by xhxhC語言指標變數
- GO語言————6.7 將函式作為引數Go函式
- Go語言Slice作為函式引數詳解Go函式
- C語言 函式指標C語言函式指標
- C語言 將函式(有參、無參)作為引數傳遞C語言函式
- c語言函式指標的定義C語言函式指標
- 【C語言】函式的概念和函式的呼叫(引數傳遞)C語言函式
- C語言函式指標與回撥用函式C語言函式指標
- C語言關於指標,gets()和gets_s()函式的理解C語言指標函式
- C語言第九周作業(指標變數,記憶體訪問,取址,空指標)C語言指標變數記憶體
- C語言用二維陣列作為函式入口引數的小結C語言陣列函式
- 物聯網學習教程— 字元指標作函式引數字元指標函式
- 函式作為引數傳遞函式
- C語言可變引數詳解C語言
- 巨集_變數_函式_指標_標頭檔案變數函式指標
- 各個程式語言語言的檔案/函式/變數的命名方法函式變數
- C語言函式指標與回撥函式使用方法C語言函式指標
- 我對函數語言程式設計的理解函數程式設計
- 可變資料型別不能作為python函式的引數資料型別Python函式
- python---函式引數、變數Python函式變數
- 傳遞指標引數(函式內部給指標賦值)示例指標函式賦值
- C語言怎麼實現可變引數C語言
- Swift 呼叫 Objective-C 的可變引數函式SwiftObject函式
- C語言語法基礎--S2函式和指標C語言函式指標
- 型別的本質:對變數、型別、指標的理解型別變數指標
- Python中將函式作為另一個函式的引數傳入並呼叫Python函式
- 為什麼C語言Scanf函式對字串不要加取地址運算子?而整型變數要加?C語言函式字串變數
- python函式變長引數Python函式
- C語言指標C語言指標
- PHP 函式可變數量的引數列表PHP函式變數
- 在實驗中觀察指標——C++ 函式引數的壓棧順序指標C++函式
- GO語言————6.2 函式引數與返回值Go函式
- typedef void (*Fun) (void) 的理解——函式指標——typedef函式指標函式指標
- 將使用回撥函式作為引數的函式改造為返回 Promise 的一個具體例子函式Promise
- 【不在混淆的C】指標函式、函式指標、回撥函式指標函式
- c++中物件的引用作為函式的引數C++物件函式
- 理解函數語言程式設計中的函式組合--Monoids(二)函數程式設計函式Mono