指標就是指標,指標變數在32 位系統下,永遠佔4 個byte ,其值為某乙個記憶體的位址。指標可以指向任何地方,但是不是任何地方你都能通過這個指標變數訪問到。
陣列就是陣列,其大小與元素的型別和個數有關。定義陣列時必須指定其元素的型別和個數。陣列可以存任何型別的資料,但不能存函式。
陣列的本質:
陣列是一段連續的記憶體空間
陣列的空間大小為 sizeof(array_type) * array_size
陣列名可看做指向陣列第乙個元素的常量指標,其值不能改變
指標的運算:
指標本質是變數,儲存的值被看做記憶體中的位址
指標是一種特殊的變數,與整數的運算規則為
p + n; (unsigned int)p + n*sizeof(*p);
指標之間只支援減法運算,且必須參與運算的指標型別必須相同
p1 - p2; ( (unsigned int)p1 - (unsigned int)p2) / sizeof(type);
注意:只有當兩個指標指向同乙個陣列中的元素時,指標相減才有意義,其意義為指標所指元素的下標查
當兩個指標指向的元素不在同乙個陣列中時,結果未定義
此處未定義含義:
1、當兩個指標分別指向棧空間和對空間上的陣列,則這兩個指標相減無意義
2、如同下例1,雖然兩個指標指向的陣列都在棧上,但是p0 - p2的值是由於記憶體對齊後相減得到的,也無意義
例1:char s1 = ;
int i = 0;
char s2 = ;
char* p0 = s1;
char* p1 = &s1[3];
char* p2 = s2;
int* p = &i;
printf("%d\n", p0 - p1); //輸出-3
printf("%d\n", ((unsigned int)p0 - (unsigned int)p1) / sizeof(char)); //輸出-3,等價於上一句
printf("%d\n", p0 + p2); //編譯報錯
printf("%d\n", p0 - p2); //輸出-12,無意義
printf("%d\n", p0 - p); //編譯報錯
printf("%d\n", p0 * p2); //編譯報錯
printf("%d\n", p0 / p2); //編譯報錯
指標的比較:
指標也可以進行關係運算 < <= > >=
指標關係運算的前提是同時指向同乙個陣列中的元素
任意兩個指標之間的比較運算(==,!=)無限制
例2:#define dim(a) (sizeof(a) / sizeof(*a))
——以下摘自 陳正衝《c語言深度剖析》
以指標的形式訪問 和 以下標的形式訪問指標
char* p = "abcdef";
定義了乙個指標變數p ,p本身在棧上佔4 個byte ,p裡儲存的是一塊記憶體的首位址。這塊內存在常量區,其空間大小為7 個byte ,這塊記憶體也沒有名字。對這塊記憶體的訪問完全是匿名的訪問。比如現在需要讀取字元『e 』,我們有兩種方式:
1)以指標的形式:*(p+4)。先取出p 裡儲存的位址值,假設為0x0000ff00,然後加上4 個字元的偏移量,得到新的位址0x0000ff04 。然後取出0x0000ff04 位址上的值。
2)以下標的形式:p[4] 。編譯器總是把以下標的形式的操作解析為以指標的形式的操作。p[4]這個操作會被解析成:先取出p 裡儲存的位址值,然後加上中括號中4 個元素的偏 移量,計算出新的位址,然後從新的位址中取出值。也就是說以下標的形式訪問在本質上 與以指標的形式訪問沒有區別,只是寫法上不同罷了。
以指標的形式訪問 和 以下標的形式訪問陣列
char a = "123456";
定義了乙個陣列a,a擁有7 個char 型別的元素,其空間大小為7 。陣列a 本身在棧上面。對a 的元素的訪問必須先根據陣列的名字a 找到陣列首元素的首位址,然後根據偏移量找到相應的值。這是一種典型的「具名+匿名」訪問。比如現在需要讀取字元『5 』,我們有兩種方式:
1)以指標的形式:*(a+4)。a 這時候代表的是陣列首元素的首位址,假設為0x0000ff00,然後加上4 個字元的偏移量,得到新的位址0x0000ff04 。然後取出0x0000ff04 位址上的值。
2)以下標的形式:a[4] 。編譯器總是把以下標的形式的操作解析為以指標的形式的操作。a[4]這個操作會被解析成:a 作為陣列首元素的首位址,然後加上中括號中4 個元素的偏移量,計算出新的位址,然後從新的位址中取出值。
由上面的分析,我們可以看到,指標和陣列根本就是兩個完全不一樣的東西。只是它們都可以「以指標形式」或「以下標形式」進行訪問。乙個是完全的匿名訪問,乙個是典型的具名+匿名訪問。一定要注意的是這個「以*** 的形式的訪問」這種表達方式。
另外乙個需要強調的是:上面所說的偏移量4 代表的是4 個元素,而不是4 個byte 。只不過這裡剛好是char 型別資料 1 個字元的大小就為1 個byte 。記住這個偏移量的單位是元素的個數而不是byte 數,在計算新位址時千萬別弄錯了。
下標 vs 指標
從理論上而言,當指標以固定增量在陣列中移動時,其效率高於下標產生的**
當指標增量為1且硬體具有硬體增量模型(硬體加速)時,表現更佳
注意:現代編譯器的生成**優化率已大大提高,在固定增量時,下標形式的效率已經和指標形式相當;但從可讀性和**維護角度來看,下標形式更優。
int a[10000];
int b[10000];
int* pend = &a[10000];
int* pa = null;
int* pb = null;
for(k=0; k<10000; k++)
}for(k=0; k<10000; k++)
;int* p1 = (int*)(&a + 1); //p1[-1] <==> a[4] = 5
int* p2 = (int*)((int)a + 1); //p2[0] <==> 0x02000000 十進位制為33554432
編譯執行
陣列引數
c語言中,陣列作為函式引數時,編譯器將其編譯成為對應的指標
void f(int a); void f(int* a);
void f(int a[5]); void f(int* a);
但丟失了長度資訊,所以一般情況下,當定義的函式中有陣列引數時,需要定義另乙個引數來標示陣列的大小。
例4:void f(int a[1000]) //會退化為void f(int* a)
printf("%d\n", sizeof(a));
int main()
int a[5] = ;
f(a);
return 0;
編譯執行,沒報錯
所以在作為函式引數時,陣列引數和指標引數等價
指標陣列和陣列指標分析
int指的是陣列元素的型別,而不是陣列的型別 定義陣列型別 c語言中通過typedef為陣列型別重新命名 typedef type name size 陣列型別 typedef int aint5 5 typedef float afloat10 10 陣列定義 aint5 iarray aint5...
指標與陣列,指標陣列 陣列指標
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...