<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      數組和指針背后——內存角度

      上一篇《語義陷阱-數組和指針》

      聊過數組和指針的區別,主要是對于數組和指針在內存中的訪問方式加以區分,這篇博文則從更深層的角度剖析數組和指針的聯系

      如果你也對底層感興趣、我向這篇文章會對你有所幫助,

      什么時候數組和指針相同(When an Array Is a Pointer )

      在實際應用中,他們可以互換的情形要大大多于不能互換的情形。首先再回顧一下聲明和定義,(上一篇中有提到這里在深入一下)

      聲明本身還可以進一步分為三種情況:

      1)外部數組的聲明(external array)

      2)數組的定義(它是聲明的一種特殊情況,它分配內存空間,并可能提供一個初值)

      3)函數參數的聲明

      所有作為函數參數的聲明在編譯時總是會轉換為指針(指向數組第一個元素),而其他情況的聲明,數組就是數組 ,指針就是指針

      可以用如下的圖來說明他們的關系:

       

      稍微總結一下:

      對于編譯過程中數組會轉化為指針的情況,數組和指針可以互換,比如:聲明為函數參數的時候 fun(int a [])和fun(int *a )是等同的。因為編譯的過程中fun(int a [])

      中的數組會轉化為指針形式,也就和fun(int *a )的效果一樣了。

      如果編譯到時候數組不被當做指針處理,那么聲明的時候不能等同。對于這種情況,數組和指針是不一樣的的,在運行時的表示形式也不一樣,并可能產生不同的代碼。

      對編譯器而言,一個數組就是一個地址,一個指針就是地址的地址。

      c語言標準對此做了如下說明:

      1)An array name in an expression (in contrast with a declaration) is treated by the compiler as a pointer to the first element of the array
      (paraphrase, ANSI C Standard, paragraph 6.2.2.1).

      2)A subscript is always equivalent to an offset from a pointer (paraphrase, 

      ANSI C Standard, paragraph 6.3.2.1).

      3)An array name in the declaration of a function parameter is treated by 

      the compiler as a pointer to the first element of the array (paraphrase, ANSI
      C Standard, paragraph 6.7.1).

      即:

      1)表達式中的數組名(與聲明不同)被編譯器當做一個指向該數組第一個元素的指針

      2)下標總是與偏移量相同

      3)在函數參數的聲明中,數組名被編譯器當做指向該數組第一個元素的指針

      我覺得有必要對上文中出現的“表達式”做一個解釋

      int arry[10]={,,,,,};

      int a=arry[2];

      那么第二句中的int a=arry[2];就是所謂的表達式中出現的數組名了,這個時候編譯器會把數組名arry當做指向數組第一個元素的指針,也就是arry[0]的地址

      下標總是與偏移量相同,也就是arry[2]中的下標2和arry[2]這個元素在內存中相對于第一個元素的偏移量也是2它們是相同的。這樣就能解釋用數組下標可以取得

      相應的數組中的某個元素了。(當然,在內存中還要考慮步長因素)

      有了上面的分析,下面的容易弄懂了

      如果聲明: int a[10] ,*p , i=2

      那么我們可以通過下面的任一種方式來訪問a[i](每一列為一組,共三種)

      p=a;   p=a;   p=a+i;
      p[i];   *(p+i);   *p;

      在表達式中,數組和指針是可以互換的, 因為它們在編譯器里都是指針形式,并且都能進行去下標操作。

      數組和指針的遍歷

      為了更好的理解,下面通過一個例子說明數組和指針的聯系和區別。(有點難理解~哦)

      將在內存訪問的角度來討論數組和指針遍歷

      數組遍歷:

      for(i=0;i<10;i++)

      a[i]=0

      遍歷過程:

      1)把a的左值放入寄存器R1(也就是把a的物理地址也即數組的首地址存入R1)  可提到循環外

      2)把i 的左值放入R2,同上,就是吧i 的物理地址放入R2  可移到循環外

      3)把 [R2]  的右值放入 R3 也就是把變量i  的大小放入R3,(這里有點匯編的味道)

      4)如果需要,調整R3 的步長,把R1 +R3 的值放入R4  解釋:R1為數組的首地址,R3為偏移量,所以R4 就是當前操作數的地址

      5)把0放入 [R4]

      注:上面的R1-R4 看看做是寄存器,符號 [n] 表示的是:內存地址為n的值

      ”可以移到循環外“說明它在整個過程中不會改變,比如數組的首地址,變量 i 地址

      左值和右值的概念在上面鏈接給出的博文中有闡述

      指針遍歷:

      p=a

      for(i =0 ;i < 10 ; i ++)

        *p++=0

      遍歷過程:

      1)p 所指對象的大小放入R5  可移到循環外

      2)左值 p 放入R1    可移到循環外

      3)[R0]放入R1

      4)0存到[ R1]

      5) R5+R1的結果存入R1

      6)R1 存到[R0]

      其實,這兩兩種訪問方式也可看做是對上一篇博客中的訪問方式的一個更深的理解。

      要操作一個變量就要得到這個變量的地址,取得地址的方式數組和指針的區別和聯系。這里就不在啰嗦,有興趣的朋友可以參見上一篇博文

      http://www.rzrgm.cn/yanlingyin/archive/2011/11/29/2268391.html

       為什么C把數組形參當做指針

      把作為形參的數組當做指針來考慮其實是出于效率考慮。C中,所有非數組形式的數據實參均為值傳遞形式,值傳遞也就是調用函數的時候,把實參

      拷貝一份給調用函數,就是說函數操作的是實參的拷貝而不是實參本身。(所以值傳遞的時候如果在函數中改變參數值,等調用結束后對實際的實參沒有

      影響,因為值傳遞中函數操作的只是實參的一份拷貝而并不是實參本身)

      而對于數組,如果每次執行函數都要拷貝整個數組的話,就會花費大量的時間和空間開銷,所有對于數組,C開用的機制是告訴函數數組的首地址,直接對

      數組進程操作。

      了解C++的朋友對于這應該就能更好地理解了,C++中參數傳遞分為值傳遞和引用傳遞,有興趣的可以自行查閱資料、這不是本文終點不在復數

      數組和指針的可交換性總結:Arrays and Pointers Interchangeability Summary 

      1. An array access a[i] is always "rewritten" or interpreted by the compiler as a pointer access *(a+i);
      2. Pointers are always just pointers; they are never rewritten to arrays. You can apply a
      subscript to a pointer; you typically do this when the pointer is a function argument,
      and you know that you will be passing an array in.
      3. An array declaration in the specific context (only) of a function parameter can equally
      be written as a pointer. An array that is a function argument (i.e., in a call to the
      function) is always changed, by the compiler, to a pointer to the start of the array.
      4. Therefore, you have the choice for defining a function parameter which is an array,
      either as an array or as a pointer. Whichever way you define it, you actually get a
      pointer inside the function.
      5. In all other cases, definitions should match declarations. If you defined it as an array,
      your extern declaration should be an array. And likewise for a pointer.

      1)對于a [i]這種形式的訪問數組,通常被解釋為指針形式*(a + i)   也就是上文中所說的“表達式”的情形

      2)指針就是指針,沒有說指針轉化為數組的情況,你可以用下標的形式去訪問指針,但一般都是指針作為函數參數時,而且傳入的是一個數組

      3)在函數參數的聲明中,數組可以看做指針,(也只有這種情況)

      4)當把一個數組定義為函數參數時,可以定義為數組,也可以是指針

      5)其他的所有情況,聲明和定義必須匹配。如果定義了一個數組,在其他文件中對它也必須聲明為數組。指針也一樣。

       

      參考資料:《expert c programming》

       

      如轉載請注明出處:http://www.rzrgm.cn/yanlingyin/

      一條魚@博客園

      2011-12-6

       

       

       

       

       

       

      posted @ 2011-12-06 12:37  Geek_Ling  閱讀(8658)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 黑森林福利视频导航| 亚洲男人第一无码av网站| 国产精品一区二区在线蜜芽tv| 国产精品中文字幕自拍| 最近日本免费观看高清视频| 国产成人免费永久在线平台| 亚洲男人精品青春的天堂| 性欧美乱熟妇xxxx白浆| 国产成人a∨激情视频厨房| 国内自拍小视频在线看| 亚洲高清国产拍精品熟女| 漂亮人妻中文字幕丝袜| 天堂在线最新版在线天堂| 久久综合国产精品一区二区| 亚洲中文字幕国产精品| 中文字幕一区有码视三区| 国产精品久久久久aaaa| 深夜释放自己在线观看| 亚洲丶国产丶欧美一区二区三区| 99久久免费只有精品国产| 招远市| 亚洲av永久无码精品网站| 成人午夜电影福利免费| 大肉大捧一进一出视频| 亚洲首页一区任你躁xxxxx| 无码熟妇人妻av影音先锋| 99久久伊人精品综合观看| 欧美精品18videosex性欧美| 亚洲天堂av日韩精品| 台中市| 在线看国产精品自拍内射| 邻居少妇张开腿让我爽了一夜| 临武县| 国产精品视频中文字幕| 精品无码国产日韩制服丝袜| 护士张开腿被奷日出白浆| 亚洲国产精品成人无码区| 亚洲人成网站在线播放2019| 欧洲极品少妇| 亚洲人成电影在线天堂色| 国产农村老熟女乱子综合|