咱們舉一個這種變相使用的例子:數組名同時也是該數組首元素的地址。也就是說,若是flizny是一個數組,下面的式子是正確的:編程
flizny == &flizny[0] //數組名是該數組首元素的地址數組
flizny和&flizny[0]都表明首元素的地址。二者都是常量,由於在程序運行過程當中它們保持不變。然而能夠把它們做爲賦給指針變量的值,而後您能夠修改指針變量的值。如程序清單10.8所示,請注意給指針加上一個數的時候,它的值會發生什麼變化?(指針說明符%p一般以十六進制形式顯示值)。指針
程序清單10.8 pnt_add.c程序code
//pnt_add.c -- 指針加法 #include <stdio.h> #define SIZE 4 int main(void) { short dates[SIZE]; short *pti; short index; double bills[SIZE]; double *ptf; pti = dates; //把數組地址賦給指針 ptf = bills; printf("%23s %10s\n","short","double"); for (index=0;index<SIZE;index++) printf("pointers + %d:%10p %10p\n",index,pti+index,ptf+index); return 0; }
輸出結果以下:對象
short double pointers + 0:0x0064fd20 0x0064fd28 pointers + 1:0x0064fd22 0x0064fd30 pointers + 2:0x0064fd24 0x0064fd38 pointers + 3:0x0064fd26 0x0064fd40
第二行打印兩個數組的起始地址,第3行是地址加1的結果,等等。請注意地址是16進制的,所以,30比2f大1,比28大8。怎麼回事?內存
ox0064fd20 + 1 等於 0x0064fd22 ?it
0x0064fd30 + 1 等於 0x0064fd38 ?io
真奇怪!咱們的系統是按字節編址的,可是short類型使用2個字節,double類型使用8個字節。在C中,對一個指針加1的結果是對該 指針增長一個存儲單元(storage unit)。對於數組而言,地址會增長到下一個元素的地址,而不是下一個字節。這就是在聲明指針時必須聲明它所指向對象的類型。計算機須要知道存儲對象所用的字節數,因此只有地址信息是不夠的(即便指針是指向標量的,也須要聲明指針類型;不然*pt操做是不能正確返回數值的)。編譯
如今咱們可以清楚地定義指向int的指針、指向float的指針,以及指向其餘數據對象的指針:class
* 指針的數值就是它所指向的對象的地址。地址的內部表示方式是由硬件來決定的。不少種計算機都 是以字節編址的,這意味着對每一個內存字節順序進行編號。對於包含多個字節的數據類型,好比double類型的變量,對象的地址一般指的是其首字節的地址。
* 在指針前使用運算符*就能夠獲得該指針所指向的對象的數值。
* 對指針加1,等價於對指針的值加上它指向的對象的字節大小。
下面的等式體現出了C的優勢:
dates + 2 == &dates[2]; //相同的地址
*(dates + 2) == dates[2]; //相同的值
這些關係總結了數組和指針間的密切關係:
能夠用指針標識數組的每一個元素,並獲得每一個元素的數值。從本質上說,對同一個對象有兩種不一樣的符號表示方法。C語言標準在描述數組時,確實藉助了指針的概念。例如,定義ar[n]時,意思是*(ar+n),即「尋址到內存中的ar,而後移動n個單位,再取出數值」。
順便提一下,請注意區分*(dates + 2)和*dates + 2。間接運算符的優先級高於+,所以後都等價於*(dates)+2。
*(dates+2) //dates的第3個元素的值
*dates + 2 //第一個元素的值和2相加
理解了數組和指針的關係,編程時就能夠方便地選擇二者中任意一種方法。例如程序清單10.9和程序清單10.1編譯後的結果同樣。
程序清單10.9 day_mon3.c 程序
/*day_mon3.c --使用指針符號*/ #include <stdio.h> #define MONTH 12 int main(void) { int days[MONTH] = {31,28,31,30,31,30,31,31,30,31,30,31}; int index; for (index=0;index<MONTH;index++) printf("Month %2d has %d days.\n",index+1, *(days+index)); //與days[index]相同 return 0; }
此處,days是數組首元素的地址;days+index是元素days[index]的地址;*(days+index)是這個元素的值,與days[index]等價。