在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

    
    
    <address id="vxupu"><td id="vxupu"></td></address>

      <pre id="vxupu"><small id="vxupu"></small></pre>
      <dfn id="vxupu"></dfn>
      <div id="vxupu"><small id="vxupu"></small></div>
    1. 新聞中心

      EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 多維數組與指針

      多維數組與指針

      作者: 時間:2016-12-01 來源:網絡 收藏
      C語言中數組和指針之間存在一些千絲萬縷的聯(lián)系,搞不清楚的情況下非常容易出錯,在前一段時間我寫過關于數組和指針的分析,但是還是存在很多不清楚的問題,特別是當出現(xiàn)一些復雜的問題時,這種情況更加的復雜。看了很多網友的博客,但是發(fā)現(xiàn)一些問題,做一下簡要的總結吧。


      多維數組的數組名并不是很多網友描述的多級指針,我僅以二維數組作為研究對象,進行一定的分析。

      二維數組int A[M][N],可以認為是存在M個元素的數組,且每一個元素都是長度為N的int型數組,這樣就能比較清晰的理解了數組。數組名在很多情況下轉換為指針,且數組名是數組首個元素的指針,這是非常重要的概念,搞清楚了這個概念也就能夠分析其他多維的數組情況啦。

      對于上面的數組A[M][N],數組名A實質上指向數組的首個元素的指針,也就是說這時的數組名A變質為一個指針,指向的類型為int[N],即指向的是一個數組,而不是一個簡單的值,那么對數組名進行解引用*A,就是得到這個一維數組(這是指針解引用的定義,就如同 int *p = &a, *p 實質上是指a是一個道理),相當于得到了一維數組名,即*A實質上是一個數組,(*A)可以看做這個數組的數組名,這和int a[N]是同樣的道理,即:a = *A。同樣根據數組名是指向數組的首個元素的指針,可以將*A也可以被看做為指針,但此時的指針指向的是數組A[0]的首個元素,也就是指向了A[0][0],也就是說*(*A)就是A[0][0]。由此可知,二維數組并不是簡單的指向指針的指針,而是每一次解引用對應的都是不同的指針類型。

      對于多維的數組,假設存在int B[N][M][S]這個三維的數組,那么數組名B是一個指針,其指向的類型是int[M][S]。*B也是指針,但是其指向的類型是int[S]。**B同樣也是指針,但是指向的類型是int型。更多維的數組也可以采用類似方法的分析。所以說并不能說是多維數組的數組名多級指針,因為多維數組對數組名的解引用操作都得到了一個不同大小的數組空間的指針,并不是指向單一元素的指針。

      由上面的分析可知,二維數組名A是一個指向一維數組的指針,指針的加法是指在當前地址上加上類型的長度,得到指向的新地址,這里的類型就是數組int[N]。因此A+i實質上是指向二維數組的第i個元素,也就是第i個一維數組。對A+i解引用*(A+i)即得到一個數組A[i],*(A+i)就是這個數組的數組名(這樣說可能不合適,但是方便理解),同時依據數組名就是指向這個數組的首個元素的地址,可知*(A+i)實質上還是一個指針,但是這個指針指向的是A[i][0]這個元素。

      下面總結一下二維數組中的一些結論:
      a :指向一維數組的指針。a -> a[0]

      *a :得到一維數組a[0],可認為(*a)是一維數組的數組名,而(*a)-> a[0][0]。

      *a+j :指向a[0][j]的指針,(*a)可視為一個一維數組名。

      a+i :數組a[i]的指針,也就是說a+i->a[i]。

      *(a+i): 得到一維數組a[i],其中*(a+i)可以視為數組名。*(a+i)指向了a[i]的首個元素,即:*(a+i)->a[i][0]。

      *(a+i)+j :得到數組*(a+i)的第j個元素的指針,即:*(a+i)+j -> a[i][j]。

      *(*(a+i)+j) :就是得到a[i][j]。

      我之前一直將二維數組看做指向指針的指針,現(xiàn)在想起來是不合適的,假設存在一個指向指針的指針int **p。如果另p = A,通常對p的操作都會導致一些錯誤,由于p是一個指向指針的指針,那么p++實質上只是增加了4個字節(jié),而A+1則增加了N*sizeof(int)。兩者之間并不是等價的關系,因此指向指針的指針并不能表征二維數組。

      如果指向指針的指針a和二維數組名是等價的,那么下面的程序肯定能夠實現(xiàn)數組元素的打印,但是非常不幸,下面的函數會產生段錯誤即訪問了非法的內存空間。

      本文引用地址:http://www.biyoush.com/article/201612/324513.htm

      int print_array(int **a, int row, int col)
      {
      int i = 0 , j = 0;
      for(i = 0; i < row; ++ i)
      {
      for(j = 0; j < col; ++ j)
      printf("%d ",a[i][j]);
      printf("");
      }
      }


      簡要的說明一下,為什么會產生段錯誤吧,由于a是一個指向指針的指針,那么a[i]則是一個指針,他指向一個數據空間,由于數組名實際上對應一個地址,這個地址和&A等都是相同的,a[i]實質上是就是數組中的一個元素,但是其中的內容也是一個指針,這時候再次解引用就很有可能導致內存非法訪問,產生段錯誤。比如A[2][3]={{1,2,3},{4,5,6}}。調用函數print_array(A,2,3)時,由于A實質上是一個地址,由于數組的特殊性,具有&A,A,A+0,&A[0][0]等對應的值是相同的。a = A,實質上a就是一個地址。這個地址就是數組的起始位置。a中的內容實質上就是數組的元素,因此對數組進行一次解引用(*a)得到的實質上就是數組的一個元素,也就是1,但是a是指向指針的指針,內容1也是一個地址,對地址1的訪問肯定發(fā)生錯誤,因為地址1處是屬于內核,不能直接進行訪問,發(fā)生了段錯誤。這也就是為什么說二維數組和指向指針的指針之間并不是等價的。

      但是根據上面的分析,我們知道二維數組的數組名指明了數組的位置,這時候直接對位置進行訪問就能夠得到數組的元素。同時我們知道a++指向的地址恰好就是a+4。剛好也就是數組的下一個元素。因此我們可以采用解一次引用的方式實現(xiàn)數據的訪問。因此上面的代碼可以修改如下,這種方法是運用了指針加法的一些特性,也就是指向指針的指針的增長大小就是大小等于4,但是這種方法只能針對類型大小為4的數組問題,其他的類型不能運用。

      int print_array(int **a, int row, int col)
      {
      int i = 0 , j = 0;
      for(i = 0; i < row; ++ i)
      {
      for(j = 0; j < col; ++ j)
      printf("%d ",*(a+i+j));
      printf("");
      }
      }

      字符串數組是比較常用的,字符串數組定義如下:

      char *str[]={
      "One",
      "Two",
      "Three",
      "Four"
      };

      字符串數組允許出現(xiàn)鋸齒形的數組,也就是說各個字符串的長度可以是不相同的,我們知道字符串數組實質上是一個指針數組,和二維數組之間存在一定的差別,并不是同一種類型的問題,指針數組可以轉換為指向指針的指針的問題。
      我們常見的主函數main的兩種種定義方式為:

      int main(int argc, char *argv[])
      int main(int argc, char **argv)

      這兩種定義方式使得很多的初學者認為二維數組和指向指針的指針有一定的聯(lián)系,特別是第2種寫法存在很大的誤導性,實質上字符串數組和二維數組之間存在很大的差別,所以不能當做一類問題來討論。

      二維數組作為函數的形參時也是一個應該注意的問題。我們已經知道二維數組不是指向指針的指針這個結論。那么如果需要傳遞一個二維數組時又該如何處理呢?我們知道數組名是一個指向數組的指針,將參數設置為這種形式即可:

      int print_array(int (*p)[N],int row, int col);
      int print_array(int a[M][N],int row, int col);

      上面的兩種定義方式是比較常見的,當然也可以采用指向指針的指針這種方式,這種方式一般在動態(tài)分配二維數組的情況下使用。這時候的動態(tài)分配的二維數組和我們當前討論的二維數組存在差別,更像是字符串指針數組問題。

      /*C++*/
      void array_create(int **array, int row, int col)
      {
      int i = 0, j = 0;

      array = new int *[row];

      for(i = 0; i < row; ++ i)
      {
      array[i] = new int[col];
      }
      }

      其中array首先分配行,然后行中保存了指針變量,這樣就實現(xiàn)了二維數組的動態(tài)分配,這時候的二維數組不再是線性表,這是需要注意的。在C語言中也可以直接創(chuàng)建線性表,即采用一維數組訪問。



      評論


      技術專區(qū)

      關閉