C语言指针系列二——指针与数组
首先让我们来回忆一下在大多数的教科书中指针与数组的用法:
#include<stdio.h>
int main()
{
int arr[] = { 1,3,5,8,9};
int* p;
for (p=arr; p < arr+ 5; p++)
{
printf_s("%d,",*p);
}
return 0;
}
其输出为
如果看官们没有指针的基础,可能会对for循环感到迷惑,但即使是有基础的人,也未必能从根本上理解这个语句。让我们慢慢看这个循环到底是怎么回事。首先是p=arr,也许有人会感到郁闷,p不是一个指向整型的指针吗,怎么可以将一个数组名赋值给它呢?让我们首先来看一下arr这个数组名更深一层的含意吧。这里arr是数组名,它有一个值,这个值就是数组的首地址。并且数组名arr是一个常量,也就是说不可能改变arr的值。先看看这个数组在内存的分布吧,必须承认,数组在内存中占有连续的内存空间:
arr是一个长度为5的整型数组的数组名,数组在内存中占有连续的内存空间。arr本身有一个值,这个值是数组的首地址。更详细地说:这个数组的首位元素是1,1是一个整型,在内存中占4个字节,arr的值就是数组首元素1的首字节的地址:
还可以通过另一种方式来获得数组首元素的地址:p=&arr[0],arr[0]是得到数组首元素,而通过&取地址符来取得数组首元素的地址。&arr[0]和arr的值是相等的。但它们代表的含义却是不一样的。arr是数组的名字,它是一个常量,标识了整个数组,其值恰好是数组首元素的地址,因为它标识了整个数组,这就不难理解它为什么会是一个常量了,对arr执行自加运算是不允许的,因为这个改变arr的值。语句&arr[0]没有什么特别的含义,按照语法的理解——就是取得数组首位元素的地址。请观看下面程序的输出:
#include<stdio.h>
int main()
{
int arr[] = { 1,3,5,8,9};
int* p;
for (p=arr; p < arr+ 5; p++)
{
printf_s("%d,",*p);
}
printf_s("%p--%p",arr,&arr[0]);
return 0;
}
输出是:
在上面的程序中,在for循环里,对p进行自加运算就是将p指向数组的下一个元素,又因为arr的长度为5,通过p<arr+5条件能够保存不会访问数组外的内容,因此for循环能够刚好输出数组里面的所有内容。这种遍历数组的方式对所有的数组都适用。绝大多数的C语言教材和老师都是这样讲授指针与数组的运用的,但现在我要说,如果只讲到这一点,又或者大家只知道这一点,那么就还没有理解到指针更本质的东西,但它毕竟没有错,只是肤浅了一点。
修改上面的程序,然后看输出:
#include<stdio.h>
int main()
{
int arr[] = { 1,3,5,8,9};
int* p;
for (p=arr; p < arr+ 5; p++)
{
printf_s("%d----%p\n",*p,p);
}
printf_s("%p--%p",arr,&arr[0]);
return 0;
}
输出是:
希望更加深入地理解指针及其运算,请看下一篇(前提是我已经写好^^):
《C语言指针三——指针运算本质》