▌來一個比較複雜一點點的例子:
現在我有一個函數,裏面有一個 靜態(static) 變數 a.
void function(){
static int a;
}
靜態變數 意味著變數被宣告後,
即使變數所在的子程序結束,所擁有的地址及儲存空間均不會被剷除。
我現在想做 按址傳遞(call by address) 的相反動作,
平時 按址傳遞 是為了令 子程序/函數 可以改變 主程序 變數的值,
可以在函數中做到 交換(swap) 、排序(sort) ...... 等行為。
void function(){
static int a;
}
靜態變數 意味著變數被宣告後,
即使變數所在的子程序結束,所擁有的地址及儲存空間均不會被剷除。
即使變數所在的子程序結束,所擁有的地址及儲存空間均不會被剷除。
平時 按址傳遞 是為了令 子程序/函數 可以改變 主程序 變數的值,
可以在函數中做到 交換(swap) 、排序(sort) ...... 等行為。
▌嗯。
現在我想把行為倒轉, (至於為什麼要這樣做?說到 垃圾回收 某篇再解釋。
令 主程序 可以改變 子程序/函數 裏靜態變數的值。
(注意祇有 靜態變數 才可以,
因為正常方式宣告的變數,所擁有的空間會在子程序返回時被消滅)
令 主程序 可以改變 子程序/函數 裏靜態變數的值。
因為正常方式宣告的變數,所擁有的空間會在子程序返回時被消滅)
▌所以要怎麼做呢?
先做個比較簡單有回傳的:
int *function(){
static int a;
return &a;
}
int main(){
int *get_a = function();
*get_a = 1;
return 0;
}
上面的程序改變了 a 的數值。
int *function(){
static int a;
return &a;
}
int main(){
int *get_a = function();
*get_a = 1;
return 0;
}
▌做了什麼?:
函數 function() 回傳了 a 的地址,地址的類型為 int* 。
(即所謂的回傳指標 (指標這個字眼真的很抽象
同樣類型為 int* 的 get_a 接收了 a 的地址,
然後基於這個地址的取值,改變了 a 的數值(儲存空間)。
每一格空間都有唯一的地址,只要依據某一個地址,就可以鎖定某一格空間。
可以回去看 Day 3 的圖,原理完全一樣,只不過 a 換成 get_a , b 換成 a 。
......
(即所謂的回傳指標 (指標這個字眼真的很抽象
同樣類型為 int* 的 get_a 接收了 a 的地址,
然後基於這個地址的取值,改變了 a 的數值(儲存空間)。
每一格空間都有唯一的地址,只要依據某一個地址,就可以鎖定某一格空間。
▌在某些情況下,我們不希望地址以回傳方式接收:
-
可能是 無法確保地址一定被接收了。
因為可以空運行有回傳的函數。 eg. function();
(前面沒有等號
可以引發嚴重的問題,例如之後會提到的 malloc(),會導致內存洩漏。
.
-
可能是 嚴格的代碼編寫風格/規範,
就像接口/介面的約定,保證了輸入輸出。
.
-
可能是 想回傳值只用作錯誤碼檢測,
方便調試 和 例外處理,
例如 fopen_s() 的情況。
下一篇介紹 不使用回傳地址方式 的複雜例子。
可能是 無法確保地址一定被接收了。
因為可以空運行有回傳的函數。 eg.
可以引發嚴重的問題,例如之後會提到的 malloc(),會導致內存洩漏。
.
因為可以空運行有回傳的函數。 eg.
function();
(前面沒有等號可以引發嚴重的問題,例如之後會提到的 malloc(),會導致內存洩漏。
.
可能是 嚴格的代碼編寫風格/規範,
就像接口/介面的約定,保證了輸入輸出。
.
就像接口/介面的約定,保證了輸入輸出。
.
可能是 想回傳值只用作錯誤碼檢測,
方便調試 和 例外處理,
例如 fopen_s() 的情況。
方便調試 和 例外處理,
例如 fopen_s() 的情況。
0 Comments
發佈留言