(原創) 當array傳至function時,是pass by value還是pass by address? (C/C++) (C)
當學會C/C++用pointer實作pass by address後,再看到array傳進function,直覺會馬上問自己,到底array傳進function是用pass by value還是pass by address?
array的特色就是一次可處理多個相同型態的變數,若使用pass by value,資料這樣copy進來copy出去,勢必會降低執行速度,所以理應使用pass by address,我們用以下的小程式做實驗。
2(C) OOMusou 2006 http://oomusou.cnblogs.com
3
4Filename : ArrayPassToFunction.cpp
5Compiler : Visual C++ 8.0 / ISO C++
6Description : Demo how to pass array to function
7Release : 12/27/2006 1.0
8*/
9
10#include <iostream>
11
12using namespace std;
13
14//void foo(int []);
15void foo(int *);
16
17int main() {
18 int ia[] = {1, 2, 3};
19 cout << sizeof(ia) << endl;
20
21 //foo(&ia[0]);
22 foo(ia);
23
24 return 0;
25}
26
27//void foo(int ia[]) {
28void foo(int *ia) {
29 cout << sizeof(ia) << endl;
30}
執行結果
4
請按任意鍵繼續 . . .
以上的程式是一個標準將array pass到function的寫法,初學者可能會認為14行的function prototype和27行的寫法比較容易懂,若以程式可讀性的角度來說是較好沒錯,一看就知道傳的是array,但這種寫法看不出這個array是pass by value還是pass by address,是事實上,這只是C/C++的一個syntax sugar而已,compiler會將14行和27行程式改寫成15行和28行的寫法...。
int *ia,一個指向int的pointer ia,在之前我們學習將int傳進function時,若想用pass by address的方式,我們會將function寫成void foo(int *i);然後用foo(&i)的方式呼叫之,所以看到28行的參數寫法,可以猜出應該是想使用pass by address的方式將array傳進去,事實上,C/C++的想法就是將『array第一個元素的位址』傳進去,既然第一個元素位址知道了,其他元素的位址也就可以推算而來,進而存取該元素...。
既然是傳位址,為什麼沒看到使用&取 address呢?事實上原本應該是如21行的寫法:&ia[0],將ia array第一個元素的位址取出,但array剛好有一個特性,ia = &ia[0],也就是『array名稱就是array第一個元素的記憶體位址』,既然如此,就可以把foo(&ia[0])改寫成22行的foo(ia)。
這個小程式做了很有趣的實驗,19行印出了sizeof(ia),29行也同樣的印出sizeof(ia),但結果卻不同,19行的ia是一個array,所以sizeof(ia)為整個array的大小,4*3=12 byte,但29的行的ia指是一個pointer,所以sizeof(ia)為4 byte而已,在此也證明了,array傳進function並非copy by value,若為copy by value,29行的sizeof(ia)也該是12 byte才對,正因為是copy by address,所以才只有4 byte,為int pointer的大小而已。
(02/08/2007更新)
除了因為速度的原因外,array有兩個特殊的特性:1.不能copy/assign(C++ Primer 4th P.112),2.array對pointer可自動轉型(C++ Primer 4th P.122),基於第一個特性,array無法使用copy by value的方式傳進function,基於第二個特性,使的array可輕易的轉成pointer,所以array傳進function時,是以pointer的形式傳進去。
(02/08/2007更新)
實務上該用27行還是28行的寫法呢?C++ Primer 4th P.239建議使用28行pointer寫法,讓人一目了然知道傳進去是一個指向array的pointer,而不是array,這是C/C++和其他語言差異頗大之處,以下是C++ Primer 4th P.239的原文。
It is usually a good idea to define array parameters as pointers, rather than using the array syntax. Doing so makes it clear that what is being operated on is a pointer to an array element, not the array itself.
See Also
(原創) array和pointer一樣嗎? (C/C++) (C)