注:
· 數(shù)組名只有被&和sizeof修飾的時候代表的是整個數(shù)組潭枣,其余其他情況代表的是數(shù)組首元素的地址 (舉例:對于數(shù)組a 甲雅,a和&a的地址是一樣的步咪,但意思不一樣侣诺,a是數(shù)組首地址,也就是a[0]的地址熄浓,&a是整個數(shù)組的首地址)
· 數(shù)組名是個常量指針情臭,它只能當右值使用不可當左值使用芒炼。
· [ ]不是數(shù)組特有的运提,只有在聲明數(shù)組變量的時候才跟數(shù)組有關(guān)系拌蜘,除此之外彼棍,通過數(shù)組名a[1],這種形式調(diào)用數(shù)組元素跷乐,就是下標運算肥败。
一級指針,可以當作一維數(shù)組使用
int *a[2] = {0,1}; //定義了數(shù)組a
int *p = a; //定義了指向int類型變量的指針p愕提,并且把數(shù)組a的首元素地址賦值給p
//那么可以通過指針p去訪問數(shù)組內(nèi)的元素馒稍, p[0] == 0; p[1] == 1;
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
程序輸出是什么。
分析:
這里主要是考查關(guān)于指針加減操作的理解浅侨。
對指針進行加1操作纽谒,得到的是下一個元素的地址,而不是原有地址值直接加1仗颈。所以,一個類型為 T 的指針的移動椎例,以 sizeof(T) 為移動單位挨决。
因此,對上題來說订歪,a是一個一維數(shù)組脖祈,數(shù)組中有5個元素; ptr 是一個 int 型的指針刷晋。
&a + 1: 取 a 的地址盖高,該地址的值加上 sizeof(a) 的值,即 &a + 5*sizeof(int)眼虱,也就是 a[5] 的地址喻奥,顯然當前指針已經(jīng)越過了數(shù)組的界限。
(int *)(&a+1): 則是把上一步計算出來的地址捏悬,強制轉(zhuǎn)換為 int * 類型撞蚕,賦值給 ptr。
*(a+1): 輸出2过牙。 分析:a,&a的地址是一樣的甥厦,但意思不一樣,a是數(shù)組首地址寇钉,也就是a[0]的地址刀疙,&a是對象(數(shù)組)首地址,a+1是數(shù)組下一元素的地址扫倡,即a[1],&a+1是下一個對象的地址谦秧,即a[5]。
*(ptr-1): 輸出5。因為 ptr 是指向 a[5]油够,并且 ptr 是 int * 類型蚁袭,所以 *(ptr-1) 是指向 a[4] ,輸出5石咬。
解答:
程序輸出: 2,5
C語言中的方括號[ ]有三種作用
1揩悄、聲明變量的時候有[ ],表示數(shù)組
2鬼悠、地址+[n](n是正整數(shù)删性,0,1焕窝,2……),表示下標運算
3蹬挺、函數(shù)參數(shù)類型中有[ ],表示指針
第一種:表示數(shù)組
表現(xiàn)形式:聲明變量的時候有[ ]
例如:
int a[10]; //這里[ ]指定a是一個數(shù)組它掂,元素類型為int
int* a[10]; //這里[ ]指定a是一個數(shù)組巴帮,元素類型為指針,即指針數(shù)組
int (*a)[10];//這里a雖然是指針虐秋,但是[ ]表明a指向的空間是數(shù)組類型榕茧,即a是數(shù)組指針
第二種:表示下標運算
表現(xiàn)形式:地址+[n](n是正整數(shù),0客给,1用押,2……)
例如:
int a[10] = {0};
a[0] = 1; //此處的[ ]表示下標運算
int *p = a;
p[1] = 2; //此處的[ ]表示下標運算
下標運算的執(zhí)行過程如下:a[1]為例
1、找到地址a: a是數(shù)組的名字靶剑,數(shù)組的名字就是數(shù)組首元素的首地址
2蜻拨、根據(jù)下標1找到新的地址: 即此時地址為a + 1
3、讀或者寫該地址內(nèi)容: a[1] = 12;次操作為寫桩引,a[1]缎讼;此操作為讀
同理,指針變量p裝的是地址,所以指針變量p可以進行下標運算坑匠,即p[2] = 12;
也可以理解成 *(a+1),效果等價休涤。
注意,初學者的誤區(qū)糾正:[ ]不是數(shù)組特有的笛辟,只有在聲明數(shù)組變量的時候才跟數(shù)組有關(guān)系功氨,除此之外,通過數(shù)組名a[1]手幢,這種形式調(diào)用數(shù)組元素捷凄,就是下標運算。
第三種:表示指針
表現(xiàn)形式:出現(xiàn)在函數(shù)參數(shù)中
例如:
void fun(int a[]); //此時編譯器會把a解讀為指針變量围来,即void fun(int a)
void fun(int a[][3]); //此時編譯器會把a解讀為數(shù)組指針變量跺涤,即void fun(int (a)[3])
void fun(int *a[]); //此時編譯器會把a解讀為二級指針變量匈睁,即void fun(int **a)
從兩方面接受此規(guī)定:
1、void fun(int a[]); //若是數(shù)組桶错,就一定要指定元素個數(shù)的航唆,不然報錯(此種聲明方式)
//而此處正常編譯通過
2、
void fun(int a[][3])
{
Printf (“%d\n”, sizeof(a)); //結(jié)果是4院刁,一個指針變量的大小
}
誤區(qū):int a[2][3] 對應(yīng)的指針類型是 int a;
這是不對的糯钙,指針的的個數(shù)跟[ ]的個數(shù)無直接關(guān)系,只與類型相關(guān)退腥。
建議:此種方式傳遞指針任岸,需要對指針有一定的深入的見解。
為了方便初學者理解狡刘,減少負擔享潜,大家可以根據(jù)以下,決定自己的參數(shù)怎么寫
1嗅蔬、
void fun(int a[][3]){;} //第一個[ ]可以不指定元素個數(shù)剑按,但是第二個必須指定,并且和調(diào)用處的指定 一樣澜术,不然提示類型匹配警告艺蝴。
//void fun(int (a)[3]){;} //兩種均可
int main()
{
int p[2][3];
fun(p);
}
2、
void fun(int a[3]){;} //[ ]中是否指定元素個數(shù)瘪板?寫了系統(tǒng)也不領(lǐng)情吴趴,直接解釋成指針
//void fun(int *a){;} //兩種均可
int main()
{
int p[3];
fun(p);
}
3漆诽、
void fun(int *a[]); //[ ]中是否指定元素個數(shù)侮攀?寫了系統(tǒng)也不領(lǐng)情,直接解釋成指針
//void fun(int **a); //兩種均可
int main()
{
int *p[3];
fun(p);
}