近來看了很多文章,總是有人問道怎樣向被調函數傳遞數組(一維,二維,甚至多維)
當然這一類文章有很多回答的,但是也不乏一些根本就沒有理解數組,指標的人來回答的,他們的回答總是大致差不多的,也就是數組等同於指標
數組真的是等同與指標嗎???
光靠說沒有說服力,看下面lz調試的吧
所以這裡就引出了一個問題,為什麼總有人認為數組名就是指標(也有可能老師講課的時候就是這樣講的,但是這樣的老師估計也沒真正明白指標和數組的含義)
這是因為當一個指標變數接受了一個數組的首地址之後,數組形式和指標形式就可以互換的比如a[2],*(p+2)
這樣寫是沒有錯的,這是因為他們在底層裡面的實現都是以指標的形式來實現的,也就是數組名相當於首地址,索引就是位移量(offset),尋找一個元素就是通過首地址加上位移量就ok了,所以這樣會讓人誤以為數組名就是指標,其實不是,指標變數只是儲存了數組的地址而不是整個數組,已經給出
好了,進入正題,既然已經知道數組名並非指標(只是可以這樣引用)
那麼一維數組既然可以通過傳遞數組名將數組的地址傳遞給被調函數,那麼二維數組呢???
我我們還是來實際的調試一下便知道了
先是一維的:
編譯出來,0錯誤,0警告,說明可以傳遞
下面就試著傳遞二維數組
出現一個錯誤,提示寫的很清楚,類型不符,為什麼一維數組就可以傳遞,但是二維數組就不能傳遞呢,這裡不是改成二級指標了嗎
這裡就引出了一個問題,a到底代表是哪個地址,這是我在陳正沖的《c語言深度剖析》這本書裡面看到的,覺得講得很不錯,就拿來引用一下
他是這樣說的,a是數組名,也就相當於一個地址,但是這裡指的是第一行的首元素的首地址,因為我們可以假想二維數組是有行列組成的
所以a+1就是下一行的地址了,這與我們想要表達成第一行的第二元素的意思大不相同,所以這裡就是一個問題
然後他又說道 &a是數組的首地址,然後加1也就是向後移位當前元素的所佔單位位元組
所以我們就知道了問題所在,正是因為類型不符,那我們就強制轉換一下嘛
如下:
無錯誤,編譯成功,結果也是正確輸出的(結果就不了)
這隻是一種方法
當然我們也可以採用動態申請空間的方法,這種方法可以採用,但是因為是程式員自己申請空間,就是向堆(heap)申請空間,這裡就要注意了,使用完畢之後一定要free掉,不然很容易造成記憶體泄露的,調試如下:
這種法制要注意不要free(p),因為那樣是錯誤的,p只是個指標,不是記憶體
當然也有人用數組指標的方法,這樣也不錯,就不用像上面那樣將二維數組看成一維數組,要將行也加入到數組元素的計算中去了
當然也有更直接的一些方法,這樣雖然看起來比較笨,但是絕對是不會出錯,就是在性慘重不給出一維的長度,後面的維度都給出
代碼如下:
第一種
[cpp]
view plaincopyprint?
- #include <stdio.h>
- int sum(int a[][5],int b)
- {
- int sum_a=0;
- for(int i=0;i<b;i++)
- for(int j=0;j<5;j++)
- sum_a+=a[i][j];
- return sum_a;
- }
- int main(void)
- {
- int a[5][5],i,j;
- for(i=0;i<5;i++)
- for(j=0;j<5;j++)
- a[i][j]=i*5+j;
- printf("%d\n",sum(a,5));
- return 0;
- }
#include <stdio.h>int sum(int a[][5],int b){int sum_a=0;for(int i=0;i<b;i++)for(int j=0;j<5;j++)sum_a+=a[i][j];return sum_a;}int main(void){int a[5][5],i,j;for(i=0;i<5;i++)for(j=0;j<5;j++)a[i][j]=i*5+j;printf("%d\n",sum(a,5));return 0;}
第二種
[cpp]
view plaincopyprint?
- #include <stdio.h>
- int sum(int a[5][5])
- {
- int sum_a=0;
- for(int i=0;i<5;i++)
- for(int j=0;j<5;j++)
- sum_a+=a[i][j];
- return sum_a;
- }
- int main(void)
- {
- int a[5][5],i,j;
- for(i=0;i<5;i++)
- for(j=0;j<5;j++)
- a[i][j]=i*5+j;
- printf("%d\n",sum(a));
- return 0;
- }
#include <stdio.h>int sum(int a[5][5]){int sum_a=0;for(int i=0;i<5;i++)for(int j=0;j<5;j++)sum_a+=a[i][j];return sum_a;}int main(void){int a[5][5],i,j;for(i=0;i<5;i++)for(j=0;j<5;j++)a[i][j]=i*5+j;printf("%d\n",sum(a));return 0;}
第三種(數組指標)
[cpp]
view plaincopyprint?
- #include <stdio.h>
- int sum(int (*a)[5],int b)
- {
- int sum_a=0;
- for(int i=0;i<b;i++)
- for(int j=0;j<5;j++)
- sum_a+=a[i][j];
- return sum_a;
- }
- int main(void)
- {
- int a[5][5],i,j;
- for(i=0;i<5;i++)
- for(j=0;j<5;j++)
- a[i][j]=i*5+j;
- printf("%d\n",sum(a,5));
- return 0;
- }
#include <stdio.h>int sum(int (*a)[5],int b){int sum_a=0;for(int i=0;i<b;i++)for(int j=0;j<5;j++)sum_a+=a[i][j];return sum_a;}int main(void){int a[5][5],i,j;for(i=0;i<5;i++)for(j=0;j<5;j++)a[i][j]=i*5+j;printf("%d\n",sum(a,5));return 0;}
以上三種方法比較容易理解
好了,就總結這麼多吧,lz主要是想讓哪些對指標不是很明白的人明白指標並不是數組名,只是實現機制是一樣的,可以相互使用
當然博文中有不足之處,也歡迎大家批評指標,共同學習進步O(∩_∩)O~