在程式語言中,函式呼叫通常可分為兩類,
1.
call by value:可譯為「傳值呼叫」,呼叫函式時,傳入引數的值會存於暫存變數內,而不使用原本的變數。
2.
call by reference:可譯為「傳參考呼叫」,呼叫的程序直接使用原本的引數,其值不另行複製。
兩者的差別在於,call
by value不會更動到函式外的變數值,而call
by reference則會。
但是坊間有些書籍卻把C語言的函式呼叫歸類出call by value、call by address、call by reference,也許其意是要使讀者便於理解,但長久以來卻使不少人對此有所誤解。
之所以說C語言只有call by value,是因為函式呼叫時,不論其傳入值如何更改,呼叫方的「值」永遠不會變。
若我們定義函式如下:
type
func(type name)
{
name = .....
}
int
main()
{
type var = value;
func(var);
printf("%d",var);
return 0;
}
不管func對傳入的var做了什麼,main函式裡的值永遠都一樣。
就算傳入陣列,陣列名稱代表的「值」是陣列所在的位址,在函式裡只能對陣列內元素的值做改變,其名稱所存的「值」仍舊相同。所以C語言的函式做不到Call by reference。
若傳入指標,指標所存的「值」也是位址,所以變的只是該位址指向的值,位址仍會存於指標之中。
也就是說陣列與指標是「將位址當作值來儲存」。
坊間有些書籍之所以不這麼寫,或許是因為想把傳入陣列和指標與一般變數有所區別,才會把前兩者另外歸類為call by reference和call by address。
但實際上,C語言只能說是透過陣列和指標來達成類似這兩種呼叫型式的效果,本質上仍是call
by value。
關於call
by address,我看過三種歸類方式:
1.
將call by address歸為call by value和call by reference之外的第三類。
2.
將call by address歸為call by value中的其中一種特例,也就是傳入型態為指標的函式。
3.
call by address等於call by reference。
第1種我認為是多餘且不正確的做法,因為call by value和call by reference足以涵蓋所有的呼叫方式,不必再增加一類。
第2種可以說得通,畢竟C語言的指標是程式語言中特別的產物,且也沒有違背C語言只有call
by value的說法。
第3種感覺有些問題,假設C語言把reference和address當作一樣的東西看待,那麼這樣的觀點放到C++就不通了,因為C++另外有call by reference的做法。
而且第2種和第3種的call by address本質意義根本就不相同。
所以說,既然call
by address沒有統一的說法,不如少用,免得造成誤解。
沒有留言:
張貼留言