2 a 和 &a 的區別
3 陣列引數
4 小結
在開始之前,先思考乙個問題:陣列名可以當作常量指標使用,那麼指標是否也可以當作陣列名來使用呢?
訪問陣列中的元素有兩種訪問方式,通過下標訪問和通過指標訪問陣列
下標形式和指標形式基本是等價的,但是效率略有區別
注意:現代編譯器的生成**優化率已大大提高,在固定增量時,下標形式的效率已經和指標形式相當;但從可讀性和**維護的角度來看,下標形式更優
下標形式與指標形式之間可以相互轉換,轉換如下:
這裡 a[n] 可是可以轉換為 n[a] 的哦
下面通過乙個例子說明陣列的指標訪問和下標訪問
// 29-1.c
#include
intmain()
;int
* p = a;
int i =0;
for(i =
0; i <
5; i++
)for
(i =
0; i <
5; i++
)printf
("\n");
for(i =
0; i <
5; i++
)for
(i =
0; i <
5; i++
)return0;
}
編譯執行結果如下:
$ gcc 29-1.c -o 29-1
$ ./29-1
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
p[0] = 10
p[1] = 11
p[2] = 12
p[3] = 13
p[4] = 14
從結果我們可以看到,通過指標和陣列都可以實現訪問陣列中的元素,可以把陣列名當作常量指標使用,也可以把指標當作陣列名來使用,a[i] 和 i[a] 是等效的指標和陣列的概念不是完全相等的,二著是有區別的,我們通過乙個例子來說明指標陣列和指標的不同
// 29-2.c
#include
intmain()
// ext.c
int a=
;
編譯執行結果如下:
$ gcc 29-2.c ext.c -o 29-2
$ ./29-2
&a = 0x560167697010
a = 0x560167697010
*a = 1
a 是陣列首元素的位址,&a 是整個陣列的位址,在數值上二者是相同的,*a 表示取元素第乙個元素。
如果把 29-2.c 的第 6 行 extern int a; 改為 extern int *a; **更改如下:
// 29-2.c
#include
intmain()
再次編譯執行,結果完全不一樣了
$ gcc 29-2.c ext.c -o 29-2
$ ./29-2
&a = 0x562f0c0ba010
a = 0x200000001
段錯誤 (核心已轉儲)
為什麼會出現這個執行結果呢?編譯器編譯 ext.c 後,陣列 a 的位址就是 0x562f0c0ba010,等價於 a 的位址就是 0x562f0c0ba010。編譯 29-2.c 時,碰見 extern int* a; 就尋找其他位置定義的 a 的值,a 的位址為 0x562f0c0ba010,所以 &a 就是取 a 的位址,就是 0x562f0c0ba010,a 的值是該位址下對應的資料,為 0x200000001。*a 表示取位址值為 0x200000001 的資料,不合法,是不允許訪問的,返回段錯誤。
下面來說明一下為什麼位址 0x562f0c0ba010 對應的資料為 0x200000001,我們列印的是 %p,%p 代表的是:按十六進製制輸出資料,長度為 8 個位元組,linux 是小端序系統,低位址存放低位,陣列儲存方式如下,取 8 位元組資料為 0x200000001
a + 1 表示指向下乙個元素,a + 1是越過乙個元素,&a + 1 表示指向這個陣列最後乙個元素後面的位置,&a + 1 是越過乙個陣列,可以從下圖清晰的看到二者的指向
下面看乙個例子,更好的區分 a 和 &a
結論:將陣列名作為引數傳遞給函式時,陣列名退化為指標,一般情況下,當定義的函式中有陣列引數時,需要定義另乙個引數來表示陣列的大小
下面通過例子來驗證我們的理論
// 29-4.c
#include
void
func1
(char a[5]
)void
func2
(char b)
intmain()
;func1
(array)
;printf
("array[0] = %c\n"
, array[0]
);func2
(array)
;printf
("array[0] = %c\n"
, array[0]
);return0;
}
在 func1() 函式中,,列印 sizeof(a),陣列退化成指標,所以不管陣列長度如何,列印的都是指標的長度,由於退化成指標,所以允許 修改指標 a = null; 我們是不能修改陣列名的指向的。func1() 函式是一樣的,只是沒有指定陣列長度。
編譯執行結果如下:
$ gcc 29-4.c -o 29-4
$ ./29-4
in func1: sizeof(a) = 8
array[0] = a
in func2: sizeof(b) = 8
array[0] = b
1、陣列名和指標僅使用方式相同,陣列名本質不是指標,指標也不是陣列名
2、陣列名並不是陣列的位址,而是陣列首元素的位址
3、函式的陣列引數退化為指標
29 指標和陣列分析(下)
注 部落格中內容主要來自 狄泰軟體學院 部落格僅當私人筆記使用。測試環境 ubuntu 10.10 gcc版本 4.4.5 一 問題 陣列名可以當做指標常量使用,那麼指標是否也可以當做陣列名來使用呢?二 陣列的訪問方式 1 以下標的形式訪問陣列中的元素 int main a 1 3 a 2 5 re...
複習c語言深度剖析 28 指標和陣列分析(上)
陣列的本質 陣列是一段連續的記憶體空間 陣列的空間大小為sizeof array type array size 陣列名可看做指向陣列第乙個元素的指標常量。問題 a 1的意義是什麼?結果是什麼?指標運算的意義是什麼?結果是什麼?include int main int p null printf a...
C 28 指標和陣列分析
問題 a 1的意義是什麼?結果是什麼?指標運算的意義是什麼?結果是什麼?程式設計分析 a 1 示例 include int main int p null printf a 0x x n unsigned int a printf a 1 0x x n unsigned int a 1 陣列名看著常...