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]等价。

相关文章
相关标签/搜索