我相信很多人都跟我一樣被某些書害的不淺,在C語言中一直還把指標跟數組名混為一談。其實它們跟本就是兩樣的東西,指標就是指標,數組就是數組,網上也有很多大牛作過很多非常深入的討論,但是個人感覺有時候把問題想得太複雜了反而不好,尤其是對於新手,因為我們新手很難搞懂編譯器背著我們到底都幹了些什麼。我們有時候應該透過現象看本質,但有時候也不要太鑽牛角尖,一口吃不出個胖子,必要時“難得糊塗”,站在抽象的角度去看事情,很多所謂的“本質”歸根到底就是“規則”,讓我們返樸歸真看看標準是怎麼說的,對於新手關於數組和指標的區別和以及什麼時候“相同”只要記住《c專家編程》中提到的三個標準和三個例外就可以了:
規則1."運算式中的數組名被編譯器當作一個指向該數組第一個元素的指標。"
規則2."下標總是與指標的位移量相同。
規則3."在函數參數的聲明中,數組名被編譯器當作指向該數組的第一個元素的指標。"
在下列的情況下,對數組的引用不能用指向該數組第一個元素的指標來代替:
例外1.數組作為sizeof()的運算元,顯然此時需要的是整個數組的大小,而不是所指向第一個元素的大小
例外2.使用&操作符取數組的地址
例外3.數組是一個字串常量初始化值
一個很簡單的例子:
#include <stdio.h>char ga[]="abcdrfghik";void method(char ca[])//or char *ca{ printf(" addr of arrary param = %#x \n",&ca); //規則3 printf(" (*ca) = %c \n",*ca); printf(" addr (ca[0]) = %#x \n",&(ca[0])); printf(" addr (ca[1]) = %#x \n",&(ca[1])); printf("++ca = %#x \n\n",++ca);}int main(void){ //例外2 這個只是數組和指標能夠互換的一個例外。這裡ga代表數組,這個擷取的數組的地址 printf(" addr of arrary param = %#x \n",&ga); //規則1 printf(" (*ga) = %c \n",*ga); printf(" addr (ga[0]) = %#x \n",&(ga[0])); printf(" addr (ga[1]) = %#x \n",&(ga[1])); //例外1 printf(" sizeof ga = %d \n\n",sizeof(ga)); method(ga); return 0;}
另外,
“數組名被改寫成一個指標的參數”規則並不是遞迴定義的。數組的數組會被改寫成“數組的指標”而不是“指標的指標”
比如char c[8][10]所被改寫對應的形參為 char (*)[10],為“數組的指標”。
一個簡單的例子:
#include <stdio.h>#include <malloc.h>method(int a[3][2]){ int i=0; int j=0; for(i=0;i<=2;i++) { for(j=0;j<=1;j++) { printf("%d\n",a[i][j]); } } for(i=0;i<=2;i++) { for(j=0;j<=1;j++) { printf("%d\n",*(*(a+i)+j)); } } int k=0; for(k=0;k<=5;k++) { //a是指向 int (*)[2] 的行指標,*a即為二位元組的首行首元素的地址 printf("%d\n",*(*a+k)); }}int main(void){ int a[3][2]={{1,2},{3,4},{5,6}}; method(a); return 0;}
至於更深層的知識水到自然渠成。