越簡單越好:數組名和指針的區別


我相信很多人都跟我一樣被某些書害的不淺,在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;
}

 

至於更深層的知識水到自然渠成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM