一、指標的運算
指標可以進行三種運算:
1.指標加上整數:
如果指標p指向陣列a[i],那麼指標p + j 指向a[i + j](前提是a[i + j]存在!)
2.指標減去整數:
如果指標p指向陣列a[i],那麼指標p - j 指向a[i - j](前提 a[i - j] 存在!)
3.兩個指標相加減(兩指標必須指向同一變數!!!否則運算沒有意義的!)
當兩個指標相減時,結果是指標在記憶體上的距離,可以用陣列元素的個數來度量,所以如果指標p指向a[ i ],q指向a[ j ],那麼p - q就等於i - j.
指標比較:指標可以使用 > < = >= <= == != 等符號進行比較,(也是隻有在指標指向同一陣列時,使用關係運算子進行的指標比較才有意義!)
二、指標用於陣列的處理
由於指標的算術運算,所以我們可以通過指標的自增自減來存取陣列的元素。
#include<stdio.h>
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int *p;
for(p = &a[0];*p < a[10];p++)
{
printf("%d\n",*p);
}
return 0;
}
使用陣列下標可以寫出不用指標的迴圈,有一種論調說使用指標可以節省時間,不過對於現在的編譯器來說,實際上會自動對使用下標的迴圈進行優化,即依靠下標的迴圈會產生更好的程式碼(大佬說的 [^.^])
*和++組合使用:
#include<stdio.h>
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int *p = &a[0];// *p = a;
while (*p < a[10])
{
printf("%d\n",*p++);
}
return 0;
}
當然還有*++p、(*p)++
三、用陣列名作為指標
1.可以用陣列名作為指向陣列第一個元素的指標。例如int a[10] ; *a = 7 ;這樣就是把a[0]元素給他賦值7。通常情況下a + i 就相當於&a[i] ,*(a + i) 就相當於a[i]。
2.陣列變數本身表達地址,所以用陣列對指標初始化不用&取地址符號,int a[10]; int *p = a; 。但是陣列的每一個元素表達的是一個變數,需要取地址符&。
3.[ ]也可以對指標做,p[0] 相當於a[0] 。*也可以對陣列做, *a 相當於a[0]。
注意:當陣列變數是一個const型別的指標,就不能被賦值了!
4.陣列作為函數引數
下面我們看一個有趣的東西( It's amazing!):
#include<stdio.h>
void test1(int a[]);
int main()
{
int a[5] = {0,1,2,3,3};
printf("main中sizeof(a[]) = %lu\n",sizeof(a));
test1(a);
return 0;
}
void test1(int a[])
{
printf("函數中sizeof(a[]) = %lu\n",sizeof(a));
}
執行結果如下:
在函數test1中sizeof傳進去的陣列我們發現他的位元組大小是8!而不是陣列本身的位元組大小 20!有趣吧哈哈哈哈QAQ。這是因為陣列作為引數傳參的時候傳進去的是一個指標!就是之前我們說了的陣列變數是一個特殊的指標。陣列名在傳遞給函數的時候總是被視為指標。
這對我們有很大的意義!:
(1).在給函數傳遞普通變數時,變數的值會被複制,任何對相應的形式引數的改變都不會影響到變數。而作為實際引數的陣列我們可以改變(除非const了一下它)!
(2).給函數傳遞陣列的時間與陣列的大小半毛錢關係都沒有!(編譯器:「我根本就沒對你陣列進行復制,沒想到吧!哈哈哈」)
(3).我們可以在需要的時候吧陣列形式引數宣告為指標。(編譯器對陣列和指標的宣告完全看做是一樣滴)
注意:對於形式引數而言,宣告為陣列跟宣告為指標是一樣的;但是對於變數而言宣告為陣列跟宣告為指標是不同的!
5.用指標名當做陣列名(如下程式碼)
#include<stdio.h>
int main()
{
int a[10],*p = a, i = 0;
for(i = 0;i < 10;i++)
{
*p++ = i;
printf("%d\n",a[i]);
}
return 0;
}
四、指標與多維陣列
int a[4][5] = {{0,1,2,3,4},{10,11,12,13,14},{20,21,22,23,24},{30,31,32,33,34}};
可以把這個理解為包含四個行元素的陣列:a[0]、a[1]、a[2]、a[3],可以把a[0]
還需要記住的是陣列名為首元素的地址。有這樣的說法a不是a[0][0]的地址,但是我試了一下,結果是它們地址相同,所以總結成一句話:陣列名為首元素地址。
行指標:一個二維陣列每一行視為一個一維陣列,指向每一行的一維陣列的指標。
處理多維陣列的行:
#include<stdio.h>
int main()
{
int a[4][5] = {{0,1,2,3,4},{10,11,12,13,14},{20,21,22,23,24},{30,31,32,33,34}};
int *p,i = 0,j = 4;
i = 3;
for (p = a[i];p < a[i] + j;p++)//p = a[i]給p初始化.p < a[i] + j 中a[i]+j表示的是a[i][j]
{
*p = 0;
}
printf("%d\n",a[i][2]);//輸出驗證第i行第2列是否為0
return 0;
}
p++執行一次之後 就相當於 p +1 就相當於 a[i] +1 就相當於 a[i][1]
處理多維陣列的列:
#include<stdio.h>
int main()
{
int a[4][5] = {{0,1,2,3,4},{10,11,12,13,14},{20,21,22,23,24},{30,31,32,33,34}};
int (*p)[5],i = 2;//(*p)的括號不可省略![5]這個表示的是一維陣列的長度,不可省略!定義了一個行指標,其寬度為5(即二維陣列的列數為5)
for ( p = &a[0]; p < &a[4];p++)//p=&a[0]是把第0行那個一行的一維陣列的地址交給p這個行指標 &a[4]相當於a+4. p=&a[0]相當於p=a
{
(*p)[i] = 0;//(*p)這裡代表著a的一整行
}
printf("%d\n",a[2][i]);//輸出驗證第2行第2列是否為0
return 0;
}