一維數(shù)組
數(shù)組名
// 如下聲明
int a;
int b[10];
a稱之為標量,即單一的一個值
b稱之為數(shù)組,因為他是一些值的集合
數(shù)組名和下標一起使用,用于標識集合中某個特定的值,例如b[0]就是b集合中的第一個值,b[4]就是第五個值,每個特定值都是一個標量
b[4]的類型是整型,在c語言中,數(shù)組名的值是一個指針常量,也就是數(shù)組第一個元素的內(nèi)存地址.它的類型取決于數(shù)組元素的類型.
-
數(shù)組名具有一些和指針完全不同的特征
數(shù)組具有確定數(shù)量的元素,而指針只是一個標量值.編譯器用數(shù)組名來記住這些元素,只有當(dāng)數(shù)組名在表達式中使用時盐茎,編譯器才會為它產(chǎn)生一個指針常亮
注意數(shù)組的名稱是一個指針 常量,而不是指針 變量,意味著不能修改常量的值
int a[10];
int b[10];
int *c;
c = &a[0];
表達式&a[0]是指向數(shù)組的第一個元素的指針,但那正是數(shù)組名的本身,所以
c=&a[0] 與 c=a是一致的
a = c ,c被聲明為一個指針常量,這條語句看上去是把c值賦值給a徙赢,但是這個賦值是非法的字柠,a的值是個常量,不能被修改
下標引用
*(b+3)
b的值是一個指向整型類型的指針,所以3這個值根據(jù)整型值長度進行調(diào)整.加法運算的結(jié)果是另一個指向整型的指針(數(shù)組第一個元素向后移3個整數(shù)長度的位置),*間接訪問操作符訪問這個新位置,或者取得那里的值(右值),或者把一個新值存儲于該處(左值)
除了優(yōu)先級不同,它和使用下標訪問完全相同,
int array[10];
int *ap = array + 2;
// 指針加法運算時會對2進行調(diào)整狡赐,運算結(jié)果所產(chǎn)生的指針ap指向array[2]
ap array+2 與&a[2]對等
*ap array[2] 與 *(array+2) 對等,對數(shù)組第三個元素的內(nèi)存地址執(zhí)行間接訪問
ap[0] c語言下標引用與間接訪問表達式是一樣的,這樣,對等的表達式是*(ap+(0)) 除去0和括號,其結(jié)果與前一個表達式相等.因此,和array[2]相同
ap+6 ap指向array[2],加法運算產(chǎn)生的指針所指向的元素是array[2]向后移動6個整數(shù)位置的元素,與之相同的為array[2]+6
*(ap+6) 括號迫使加法運算先執(zhí)行,所以得到的值是array[8]
ap[6] 相當(dāng)于*(ap+(6)) 去除括號為array[8]
&ap ap的指針,是合法的
ap[-1] 使用偏移量-1可以得到前一個元素,相當(dāng)于(ap+(-1)),也就是array[1]
ap[9] 看上去是正常的,但是array的長度為10,這個表達式是越界訪問的,是非法的
指針與下標
對于指針和下標,兩種形式都可以使用,小標容易理解窑业,可讀性強,尤其在多維數(shù)組中,但指針的效率更高
// 使用下標循環(huán)
int array[10],a;
for (a=0;a<10;a++)
array[a] = 0;
// 使用指針循環(huán)
int array[10], *ap;
for (ap=array;ap<array+10;ap++)
*ap = 0;
數(shù)組和指針的關(guān)系
int a[5];
int *b;
在聲明一個數(shù)組時,編譯器將根據(jù)所指定的元素數(shù)量分配內(nèi)存空間,然后在創(chuàng)建數(shù)組名,它的值是一個常量,指向這段空間的起始位置。
在聲明一個指針時枕屉,編譯器只為指針本身保留內(nèi)存空間常柄,不為其他值分配空間,而且指針變量并不指向任何現(xiàn)有的內(nèi)存空間搀擂。如果指針時是一個自動變量西潘,它甚至根本不會被初始化。
作為函數(shù)參數(shù)的數(shù)組
當(dāng)一個數(shù)組傳遞給函數(shù)時哨颂,數(shù)組名是指向該數(shù)組的常量喷市,因此傳遞給數(shù)組的是一份指針的拷貝。函數(shù)如果執(zhí)行了下標引用威恼,實際上就是對這個指針執(zhí)行間接訪問操作品姓,并且通過間接訪問,函數(shù)可以修改和調(diào)用數(shù)組元素
由于傳遞給函數(shù)的是一份指針的拷貝,因此函數(shù)可以自由操作它的指針形參箫措,而不必擔(dān)心會修改對應(yīng)實參的指針
當(dāng)然,如果傳遞了一個指向數(shù)組的指針腹备,則會修改對應(yīng)的實參
聲明數(shù)組參數(shù)
int strlen(char *string);
int strlen(char string[]);
首先,這兩個聲明是相等的斤蔓,調(diào)用函數(shù)時實際傳遞的是一個指針.
數(shù)組初始化
int vector[5] = {1,2,3,4}
如果初始化值的數(shù)目與元素數(shù)目不匹配,編譯器會自動補全
自動計算長度
int vector[] = {1,2,3,4,5,6}
可以不必指定元素數(shù)組馏谨,數(shù)組會自動計算長度
計算元素數(shù)目
int vector[] = {1,2,3,4,5,6};
void sum(int vector[]){
int len = sizeof(vector) / sizeof(vector[0]);
//....
}
多維數(shù)組
數(shù)組名
一維數(shù)組的數(shù)組名是指向這個數(shù)組首元素的指針常量,二維數(shù)組也差不多,唯一區(qū)別是多維數(shù)組的第一維的元素又是一個數(shù)組
int matrix[3][10]
matrix這個名字實際上指向的是二維數(shù)組的第一個元素附迷,也就是指向一個包含10個整型元素的指針
matrix + 1
也是指向包含10個整型元素的指針
*(*(matrix + 1) + 5)
*(matrix + 1) 實際上等價于 matrix[1]的,
而后這個包含10整型的數(shù)組又移動了5個元素 也就是, *(matrix+1)+5
最后對這個表達式求值 *(*(matrix+1)+5)
等價于 martix[1][5]
指向數(shù)組的指針
int vector[10], *vp = vector;
int matrix[3][10],*mp = matrix;
第一個聲明是合法的,把vp聲明為一個指向整型的指針,vector和vp是相同的類型:指向整形的指針,*vp是訪問這個指針保存的值哎媚,和vector[0]一個意思
第二個聲明是非法的喇伯,matrix是一個多維數(shù)組,matrix并不是一個指向整型的指針,而是指向整型數(shù)組的指針拨与,所以應(yīng)該這樣聲明:
int (*mp)[10]
下標引用的優(yōu)先級高于間接訪問稻据,由于括號的存在,首先執(zhí)行的還是間接訪問,所以mp是個指針捻悯,接下來執(zhí)行下標引用匆赃,所以mp是指向某種類型的數(shù)組的指針。
因此 int (*mp)[10]
mp指向matrix的第一行,也就是matrix[0]
如果訪問數(shù)組元素而不是在數(shù)組中移動今缚,則需要
int *p = &matrix[0][0];
或者 int *p = matrix[0];
作為函數(shù)參數(shù)傳遞
int martix[3][10]
void func(int (*mp)[10])
void func(int mp[][10])
指針數(shù)組
#include <stdio.h>
void traversal(char **,int);
int main(void) {
char *keyword[] = {
"do","while","for","return","const","register"
};
int len = sizeof(keyword) / sizeof(keyword[0]);
traversal(keyword,len);
return 0;
}
void traversal(char **keyword,int size) {
char **i;
char *j;
for (i = keyword; i<keyword+size;i++){
printf("[");
for (j=*i;*j!='\0';j++){
printf ("%c,",*j);
}
printf("]->%s\n",*i);
}
}
上面的代碼中,keyword是一個字符串指針數(shù)組,通過長度來進行遍歷 keyword是指向保存字符數(shù)組的字符型指針,keyword是訪問字符數(shù)組,(*keyword) 是訪問字符數(shù)組的第一個元素