C Primer Plus 第10章 數組和指針 10.3 指針和數組

咱們舉一個這種變相使用的例子:數組名同時也是該數組首元素的地址。也就是說,若是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]等價。

相關文章
相關標籤/搜索