指针与数组
通过数组下标所能完成的任何操作都可以通过指针来实现。一般来说,用指针编写的程序比用数组下标编写的程序执行速度快,但另一方面,用指针实现的程序理解起来稍微困难一些。
声明一个数组
int a[10];
定义一个长度为10的数组a。换句话说,它定义了一个由10个对象组成的集合,这10个对象存储在相邻的内存区域中,名字分别为a[0]、a[1]、a[2]、......、a[9]。
指向这个数组
int *pa = &a[0];
int x = *pa;
定义一个指向整型对象的指针,并将指针指向数组a的第0个元素。即,pa的值为数组元素a[0]的地址。将数组元素a[0]的值复制到变量x中。
如果pa指向数组中的某个特定的元素,那么,根据指针运算的定义,pa+1将指向下一个元素,pa+i将指向数组元素之后的第i个元素,而pa-i将指向pa所指向数组元素之前的第i个元素。因此,如果指针pa指向a[0],那么*(pa+1)引用的是数组元素a[1]的内容,pa+i是数组元素a[i]的地址,*(pa+i)引用的是数组元素a[i]的内容。
无论数组a中元素的类型或数组长度是什么,上面的结论都成立。“指针加1”就意味着pa+1指向pa所指对象的下一个对象。相应的,pa+i指向pa所指向的对象之后的第i个对象。
下标和指针运算之间具有密切的对应关系。根据定义,数组类型的变量或表达式的值是该数组的第0个元素的地址。因为数组名所代表的就是数组第一个元素的地址,因此可以将赋值语句更改为:
int *pa = a;
对数组元素a[i]的引用也可以写成*(a+i)这种形式,在计算数组元素a[i]的值时,C语言实际上先将其转换为*(a+i)的形式,然后再求值,因为在程序中这两种形式是等价的。
所以,&a[i]和a+i的含义也是相同的,a+i是a之后第i个元素的地址。相应的,如果pa是一个指针,那么,在表达式中也可以在它的后面加下标。pa[i]与*(pa+i)是等价的。
数组不是指针
数组名和指针之间有一个不同之处,指针是一个变量。因此,在C语言中,语句pa = a
和pa++
都是合法的。但数组名不是变量,因此,类似与a=pa
与a++
形式的语句都是非法的。
将数组交给函数
当把数组名传递给一个函数时,实际上传递的时该数组的第一个元素的地址。在被调用函数中,该参数是一个局部变量,因此,数组名参数必须是一个指针,也就是一个存储地址值的变量。