今天这节课讲指针与数组的关系。
数组变量定义的语法格式是:
数据类型 数组变量名[数组长度];
数组名其实和指针变量一样,它也是一个地址。
记住:数组名是一个地址,它是数组首元素的地址。
1 数组名是数组第一个元素的地址
假设我们定义一个数组:
int a[100] ;
数组变量名a代表一个地址,它的值是数组第一个元素a[0]的地址,也叫基地址。
也就是说,a就是&a[0],&a[0]就是a。
但是数组名是地址常量,是数组第一个元素的地址,这个地址不能改变。
也就是说,不可能出下面这样的语句:
a = 表达式 ;
a不能出现在赋值号的左边,就是说不能重新给a赋值。
再强调一遍:
a[0]=100是对的,但a=100不对。
昨天说了指针的两个基本运算:取地址运算和间接访问(取地址里的内容)运算。其中取地址运算符是&,间接访问运算符是*。
假设有定义:
int a[10]={ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 } ;
此时a[0]=10, a[1]=20, ... ,a[9]=100。
数组名a是数组首元素a[0]的地址,a[0]的地址可以用运算符&取出来,所以我们说a就是&a[0]。
再次强调:a就是&a[0],&a[0]就是a 。
注意是 a是&a[0],a不是a[0]。
&a[0]是数组首元素a[0]的房号,a[0]是10(根据上述定义)。
那么*a就是*(&a[0]),所以 *(&a[0])就是10。
2 数组名a+i 是距数组首地址的第i个偏移
假设第一个元素a[0]的地址是3000,也就是说a是3000,&a[0]是3000。
假设一个int类型的地址要2个长度,那么a[1]的地址就是3002,a[2]的地址就是3004,…。
此时,a是3000,a+1就是3002,a+2是3004,a+i就是3000+2*(i-1)。
a是&a[0],a+1是&a[1],a+2是&a[2],…,a+9是&a[9]。
按定义:
int a[10]={ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 } ;
于是,*a就是a[0],*a的值是10;
*(a+1) 就是a[1],*(a+1) 的值是20;
…
*(a+9) 就是a[9],*(a+9)的值是100。
假设有定义:int a[100] ;
则图示如下:
3 当指针变量指向数组时,任何由数组下标来实现的操作都能用指针来完成
假设有定义:
int a[100] , *p ;
那么在p = a(或p = &a[0])后,
指针变量p就能和数组变量a一样用,凡是出现a的地方,均可以换成p。
程序1:
上述程序求数组元素的和,其中定义了一个指针变量p,当然这个程序中p没什么用。
程序1运行结果:
在程序1中,如果将a换成p,也是对的。
就是说,可以将语句
sum = sum + a[i];
换成:
sum = sum + p[i];
程序2:
程序2的运行结果与程序1的运行结果是一样的。
当指针变量名指向数组第一个元素时,我们可以用指针变量名代替数组名,处理完第一元素后,可以将指针变量加1,指针变量加1是让它指向了下一个元素。
程序3:
一开始p=a,p指向数组第一个元素,则*p就是a[0]。
p++后,p指向第二个元素,此时*p就是a[1]。以此类推,将所有元素的值都取出来加到了sum上。运行结果和程序1、2是一样的。
4 总结
当定义了一个数组变量和一个指针变量,而且这个指针变量指向这个数组时,如:
int a[10], *p;
p=a;
则a[i]、p[i]、*p是等价的。
今天的内容不难,但容易弄错。初学者学到这个内容时,常常产生这样的疑问,比如:
(1)为什么a[i]和p[i]是等价的?
(2)p不是指针吗?怎么可以p[i]?
其实在C语言里,用来把数组下标括起来的这个中括号[],跟指针两个基本运算里面的那个星号*是一样的,都是取出地址里面的内容。
这节课的内容确实不大好理解,可以多看几遍。不懂就问。