陣列與指標

2021-07-25 05:28:25 字數 2474 閱讀 9817

相同點就是:對陣列的引用總是轉化為對指標的引用,

不同點就是:陣列名是常量而指標是變數

從他的本質去即記憶體的分配與訪問去理解它。

我們知道定義只是乙個特殊的宣告。

定義:只能出現在乙個地方,建立新物件,同時確定物件的型別並分配記憶體。(注意這裡所說的物件跟c++中所說的物件沒有任何的關係。)

所以下來我們看乙個例子:檔案1:int mango[100];檔案2:exitern int *mango;在我們執行時總是會出錯,為什麼呢?首先我們在看一下記憶體對陣列和指標的引用:

比如說:char a[9]=」abcdefgh」; c=a[i];

編譯器符號表具有乙個位址 9980

執行時第一步:取i的值,將它與9980相加

執行時第二步:取位址(9980+i)的值。但是當:char *a=」abcdefgh」; c=a[i];時 編譯器符號表具有乙個a,位址為4624

執行時第二步:去i的值,並將它與5081相加。

執行時第三步:取位址【5081+1】的值。我們很容易看到上面對陣列記憶體是直接訪問的,而對於指標是間接訪問的。(雖然最終都可以取得所要的元素,但是訪問途徑是不一樣的!)當extern char *a;然後用a[i]來引用其中的乙個元素時,就是對:char *a=」abcdefgh」; c=a[i];的訪問步驟。所以既然把p宣告為指標,那麼不管p原先是定義為指標還是陣列,都會按照指標形式訪問元素的,但是只有當p原來定義為指標時這個方法才是有效的。然後我們分析開始的那個為什麼執行時總是出錯?mango 被宣告為extern char *mango,而它原先的定義卻是char mango[100],這種情形,當用mango[i]這種形式提取這個宣告的內容時,實際上得到的是乙個字元。但按照上面的說法,編譯器卻把它當成是乙個指標,把acsii碼解釋為位址,顯然是牛頭不對馬嘴麼。解決方案很容易:即宣告為:extern int mango;還有就是如我們定義乙個:char *p=」abcdefgh」;此時這是乙個字串常量,這個字串常量被定義為唯讀。如果試圖通過指標去修改這個字串的內容時,就會出現未定義的行為。

與指標相反的是:被字串常量初始化的陣列是可以修改其內容的。下面說一句c程式設計師的名言:千萬千萬不要忘了c語言在表示式中把乙個型別為t的陣列的左值當作是指向該陣列第乙個元素的指標。什麼時候陣列和指標可以相同呢?所有作為函式引數的陣列名總是可以通過編譯器轉換為指標。在其他所有情況下(最有趣的情況就是「在乙個檔案中定義為陣列,在另乙個檔案中宣告為指標」),陣列的宣告就是陣列,指標的宣告就是指標,兩者不能混淆。但在是用陣列(在語句或表示式中引用)時,陣列總是可以寫成指標的形式,兩者可以互換。

對編譯器而言,乙個陣列就是乙個位址,乙個指標就是乙個位址的位址。總結一下相同點的地方和不同點的地方:

宣告方面:1、extern 如extern char a;不能寫成指標形式。

2、定義,如 char a[10];不能該寫成指標形式。

3、函式的引數,如fun(char a)或fun(char *a)隨便寫,因為當陣列作為函式

引數時,編譯都將把它轉化為指標形式處理。在表示式中使用:如c=a[i]也可以隨便寫,陣列形式或指標形式都可以。

標準c規定了三條規則:陣列與指標相同

1、表示式中的陣列名(與宣告不同)白編譯器當作是乙個指向該陣列的第乙個元素的指標。

2、下標總是與指標的偏移量相同。

3、在函式引數的宣告中,陣列名被編譯器當作指向該陣列第乙個元素的指標。

在表示式中,指標和陣列是可以互換的,因為他們在編譯器裡的最終形式都是指標,並且都可以進行取下標運算。

當然也有幾個極少見的例外:在下列情況下,對陣列的引用不能用指向該陣列第乙個元素的指標來代替:

(1)、陣列作為sizeof()的運算元顯然此時需要的是整個陣列的長度,而不是指向第乙個元素的指標。

(2)、使用&取陣列的位址,它所取的是整體陣列的乙個位址。

(3)、陣列是乙個字串常量初始值時。

c語言把陣列小標該寫成指標偏移量的根本原因就是指標和偏移量是底層硬體所使用的基本模型。標準規定作為「型別的陣列」的形慘的宣告應該調整為「型別的指標」。

在函式形慘定義這個特殊情況下,編譯器必須把陣列形式改寫成指向陣列第乙個元素的指標形式,編譯器只向函式傳遞陣列的位址,而不是整個陣列的拷貝。把作為形慘的陣列和指標等同起來是處於效率原因的考慮。

在c語言中,所有非陣列形式的資料實參均以傳值形式(對實參作乙份拷貝傳遞給呼叫的函式,函式不能修改作為實參的實際變數的值,而是只能修改傳遞給他的那份拷貝)呼叫。然而,如果要拷貝整個陣列,無論是在時間上還是空間上的開銷都是很大的,而且在大多數情況下你並不需要拷貝整個陣列,只要告訴函式那個位址就可以了。

我們看一下陣列形慘是如何被引用的:fun(char p)或fun(char *p)

執行時步驟1:從sp偏移14個位置找到函式的活動記錄,取出引數

執行時步驟2:取i的值,並於5081相加

執行時步驟3:取出位址(5081+i)的內容

注意:有一樣操作只能在指標裡進行而無法在陣列中進行,那就是修改它的值。陣列名是不可修改的左值,他的值是不能改變的。

指標與陣列,指標陣列 陣列指標

int a 10 print n a p,a p a,a print n a 1 p,a 1 p a 1,a 1 a做乙個指標,步長為4,指向乙個元素,a做乙個指標,步長為40,指向乙個維陣列 int b 3 4 print n b p,b p,b p b,b,b print n b 1 p,b 1...

指標陣列與陣列指標

1.指標陣列 指標陣列中每乙個元素都是乙個指標,也既是存放字串的首位址。所以指標陣列適合處理若干個長度不等的字串。定義的一般形式為 型別說明符 指標陣列名 陣列長度 例如 int p 3 宣告乙個陣列,指標陣列p,由3個int型別指標變數元素組成 從運算子的優先順序分析,由於 的優先順序大於 所以p...

指標陣列與陣列指標

呵呵,實在是厭倦了繞口的解釋。指標陣列,故名思義,就是指標的陣列,陣列的元素是指標 陣列指標,同樣,就是直想陣列的指標。簡單舉例說明 int p 2 首先宣告了乙個陣列,陣列的元素是int型的指標。int p 2 宣告了乙個指標,指向了乙個有兩個int元素的陣列。其實這兩種寫法主要是因為運算子的優先...