[C/C++] 二維陣列的傳遞
文章推薦指數: 80 %
在c裡,陣列傳遞是採用傳址呼叫(call by address or call by pointer), ... funcB() 執行完後,不會把複製的p, q丟回給 main() ,寫成code會是這樣.
[C/C++]二維陣列的傳遞
Publishedon:
March20,2014
Tags:
C
Array
pointer
我們都知道,
C語言是以陣列第一個元素的位址當成是陣列的位址(也就是說-->陣列名稱本身就是存放陣列位址的變數),
在c裡,陣列傳遞是採用傳址呼叫(callbyaddressorcallbypointer),
因為在呼叫函數傳遞參數時,無法將整個陣列傳遞(因為陣列可能很大),因此傳的是陣列開頭的位址,
okay,複習一下參數傳遞的觀念,
分為傳值(callbyvalue)、傳址(callbyaddress)、傳參考(callbyreference)3種,
1.傳值callbyvalue
當函數被呼叫時,將主程式的變數"複製"一份給副函數,主程式的變數跟副程式複製來的變數互相獨立,並且有各自獨立的記憶體空間,
假設main()呼叫函式funcB(p,q),則funcB中的p和q是把main()傳入的參數「複製」一份,funcB()對p,q所做的任何運算都不會影響到main()中的p和q,因為funcB()執行完後,不會把複製的p,q丟回給main(),寫成code會是這樣
voidswap(inti,intj);
intmain()
{
inti=5,j=10;
printf("beforeswap:i=%d(add=%p)j=%d(add=%p)\n",i,&i,j,&j);
printf("swap()work\n");
swap(i,j);
printf("ijinmain():i=%d(add=%p)j=%d(add=%p)\n",i,&i,j,&j);
return0;
}
voidswap(inti,intj)
{
inttemp;
temp=i;
i=j;
j=temp;
printf("ijinswap():i=%d(add=%p)j=%d(add=%p)\n",i,&i,j,&j);
}
可以看到output中,main()和swap()裡的i和j是獨立的(記憶體位址也不同),
而經過swap進行變數互換後,也沒影響到main()裡原本的變數值,
當換成傳遞陣列時,可以看到結果不一樣了,
voidtimesTwo(intarr[]);
intmain()
{
intarr[3]={1,3,5};
for(inti=0;i<3;i++)
printf("beforeswap:arr[%d]=%d(add=%p)\n",i,arr[i],&arr[i]);
printf("arr[]add=%p\n",arr);
printf("swap()work\n");
timesTwo(arr);
for(inti=0;i<3;i++)
{
arr[i]=arr[i]*2;
printf("arr[]inmain():arr[%d]=%d(add=%p)\n",i,arr[i],&arr[i]);
}
printf("arr[]add=%p\n",arr);
return0;
}
voidtimesTwo(intarr[])
{
for(inti=0;i<3;i++)
{
arr[i]=arr[i]*2;
printf("arr[]inswap():arr[%d]=%d(add=%p)\n",i,arr[i],&arr[i]);
}
printf("arr[]add=%p\n",arr);
}
證實了開頭所說,C是以陣列第一個元素的位址當陣列的位址,且採用傳址(callbyaddress)方式,
呼叫副函式timesTwo()後,函數所做的改變,直接改變main()裡array的值,這就是傳址(callbyaddress),
傳址同樣可以用在一般變數,只要加上pointer即可,這方法可以讓函數直接改變原本變數值,也省去複製的步驟和記憶體空間,
voidswap(int*i,int*j);
intmain()
{
inti=5,j=10;
int*pt1=&i;
int*pt2=&j;
printf("beforeswap:\ni=%d(add=%p)\tj=%d(add=%p)\npt1=%d(add=%p)\tpt2=%d(add=%p)\n\n",i,&i,j,&j,*pt1,pt1,*pt2,pt2);
printf("swap()work\n");
swap(pt1,pt2);
printf("ijptinmain():\ni=%d(add=%p)\tj=%d(add=%p)\npt1=%d(add=%p)\tpt2=%d(add=%p)\n\n",i,&i,j,&j,*pt1,pt1,*pt2,pt2);
return0;
}
voidswap(int*i,int*j)
{
inttemp;
temp=*i;
*i=*j;
*j=temp;
printf("ijptinswap():\ni=%d(add=%p)\tj=%d(add=%p)\n\n",*i,i,*j,j);
}
swap呼叫前後,main()的ij跟swap裡ij用的都是同一塊記憶體,
經過swap後,也因此ij直接互換的結果直接改變在main()裡,
這也是為什麼callbyaddress又叫callbypointer,然後本質上他也是callbyvalue的關係了!
當寫到2維陣列(或多維陣列)時,赫然發現事情已經不是如上所想的簡單了,
首先,這樣的陣列傳遞已經無法通過compile了,因為Compiler不知如何翻譯...待會會解釋why,
voidtimesTwo(intarr[][]);
intmain()
{
intarr2[2][4]={1,3,5,7,2,4,6,8};
...
}
如果這樣寫就可以通過compile,但把維度寫死一點都不彈性,未來要傳不同維度array給函數,不就哭了,
voidtimesTwo(intarr[2][4]){};
所以要換成這樣的寫法較佳,
voidtimesTwo(intarr[][4]){};
或這樣,
voidtimesThree(int(*arr)[4]){};
結果都是一樣,並且成功傳給function顯示,
2維陣列的行和列,其實是我們為了清楚理解陣列元素排列而想像出來的,實際上在記憶體配置並非如此,而是以線性模式配置,
不管幾維陣列,都是分配成一塊連續的記憶體空間去處理陣列,
如intarr2[2][4]陣列會分配成2*4*sizeof(int)大小記憶體區塊(如圖),依此類推,
如果要走訪2維陣列的話,要把它對應成一維來處理,
假設陣列intarr2[2][4]={{1,3,5,7},{2,4,6,8}}
我們要存取arr2[p][q]的值,從記憶體觀點,我們要從arr2[p]的開頭後走q個單位到達arr2[p][q].
所以可以如此表示:arr2[p][q]=p*4+q
code可以這樣寫
voidarrFour(int*arr,introl,intcol)
{
for(inti=0;i
延伸文章資訊
- 1C++傳遞二維陣列 - 程式人生
C++中一維陣列作為函式引數傳遞應用十分普遍,原理和操作都十分簡單。陣列名就代表了陣列的首地址,下標就是偏移量。函式的形式引數宣告為一級指標即可( ...
- 2C++ -傳遞二維陣列 - 小哈的程式工作坊
C++ -傳遞二維陣列(Pass 2D array as a function parameter in C++). 二維陣列到底怎麼傳進函式?指標?還要給數量?到底是ROW 的數量還是COLU...
- 3從C++中的函式返回二維陣列 - 程式人生
Returning multidimensional array from function (7個答案) 7年前關閉。 我想使用從函式返回的二維整數陣列我應該如何定義函式的返回值?
- 4[C/C++] 二維陣列的傳遞
在c裡,陣列傳遞是採用傳址呼叫(call by address or call by pointer), ... funcB() 執行完後,不會把複製的p, q丟回給 main() ,寫成cod...
- 5Re: [語法] 回傳一個二維陣列- 看板C_and_CPP
首先呢,陣列在C/C++ 中並不是first-class object 至少你不能回傳一個陣列但是你可以回傳一個指向陣列的pointer 這是合法的然而C 的語法有個非常奇怪 ...