程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 菜鳥談談二維數組,菜鳥二維數組

菜鳥談談二維數組,菜鳥二維數組

編輯:關於C語言

菜鳥談談二維數組,菜鳥二維數組


在學C語言的時候,每次遇到二維數組,都特別頭疼,並不是它難用,而是我搞不清楚它的數組名代表的是什麼。但我們知道:當我們定義一個一位數組的時候,它的數組名就是第一個元素的地址,也就是,下面的語句是等價的:

int a[3]={1,2,3};
printf ("%d\n",a);
printf ("%d\n",&a[0]);

  他們將會輸出相同的值,而且更重要的是,他們的意義是一樣的。因為在數組訪問成員的過程中,它是完全轉化成指針的形式來間接訪問的,也就是:

a[i]等價於*(a+i)
&a[i]等價於(a+i)

  也就是根據這種思想,我們來看看二位數組:

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printf ("%u\n",a);    //地址我們使用%u來輸出,防止地址過大。
printf ("%u\n",a[0]);
printf ("%u\n",&a[0]);

  在一個二位數組中,上面輸出結果的數值是一樣,但,僅僅是數值一樣而已,他們的意義是大不一樣的。那麼,上面的二維數組名到底和誰等價呢?  答案是&a[0];//行地址

      其實,C語言並沒有二維數組,但C語言有一維數組,那麼,要模仿出N維數組,也就不是難事了。所以,二維數組只是數組的數組,只不過數組的沒一個元素也是一個數組罷了。

     那麼就是,每一個元素a[i]代表的就是一個數組,那我們用一維數組來理解,就不是難事了。上面說過,在一維數組中,數組名和第一個元素的首地址是等價的就是a <-->&a[0];(一維數組)。

     那麼,我們的數組的數組(二維數組),每一個元素都是一個數組,

    所以a[0] <--> &a[0][0];//這裡代表的是列地址,後面會區分列地址和行地址的區別

    所以 a     <--> &a[0];//這裡代表的是行地址

到了這裡,我們已經知道了二維數組的數組名的含義,和它與那個等價。那麼,我們現在看看行地址和列地址的區別。

   其實,在上面二維數組的代碼中,輸出的結果是一樣的,但是,他們的含義是大相徑庭的。含義不同?區別在哪裡呢?區別就是:在指針的移動中。

   我們知道,在指針的移動是以數據類型所占字節大小為單位進行移動的。兩個指針所指向的地址可能相同,但他們的單位卻很可能不同。

int b[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printf ("%u\n",b+1);//+16
printf ("%u\n",b[0]+1);//+4
printf ("%u\n",&b[0]+1);//+16

     可以看到,同樣是加一,但是指針移動的距離卻很是不同(本人覺得這點很重要)。這是因為,b和&b[0]是等價的,而且,他們代表的是行地址,也就是,每次移動1個單位,就移動一行的距離。

     而b[0]等價於&b[0][0],代表的是列地址,每次移動,只移動sizeof(b[0][0])個字節,就是一個元素所占的字節,這就是它們含義不同的一個區別。

 

     在我以前用memset函數的時候,最怕要用到二維數組, 我真的不知道是傳入a,a[0],&a[0],還是&a[0][0]。我們知道,他們的值是一樣的,只是代表的含義不一樣,我們需要傳入哪一個呢?其實,那個都行,這已經不是二維數組的知識了,這關乎到void *指針和memset函數內部處理的方式,

void *memset( void *dest, int c, size_t count );  //memset函數的聲明

void *指針,代表的一個地址,僅僅是一個地址,我們不考據他們的含義,為什麼呢?剛不是說指針的含義很重要嗎?現在又不考據?這是因為,memset函數可以把任可的內存置成某一個值,我們可以傳int *,double * ,float *,char *甚至struct _Person *。我們沒可能每個類型都寫一個函數,因為我們有了結構體這個類型後,數據類型已經不能捉摸了。所以,我們要做到這一點,只能僅僅傳入一個地址,我們一個字節一個字節地處理(因為計算機是已字節為單位的).下面就貼代碼算了,已經不是二維數組的知識了。

void *mymemset(void *str,int number,int ByteSize)
{
    char *ptr = (char *)str;
    int i;
    for (i=0;i<ByteSize;i++)
    {
        *ptr=number;
        ptr++;
    }
    //*ptr='\0';//調用完memset後,如果是字符串的話,記得設置結束符
    return str;
}

      以上僅是個人理解觀點,如有錯誤,希望讀者們指出,樓主感激不盡。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved