目录
1.数组名
数组名的值是一个指针常量,也就是数组第一个元素的地址;
运行下列程序验证这个说法:
//例子1.1
#include<stdio.h>
int main()
{
int a[10];
printf("a的地址%p\n",a);
printf("a[0]的地址%p\n",&a[0]);
return 0;
}
运行的结果如下:
![运行结果](https://i-blog.csdnimg.cn/blog_migrate/2f213277a78b7bc670dcbe048272f0ee.png)
这告诉了我们两件事情:
1.指针常量(即数组名)所指向的是内存中数组的起始位置;
2.表达式&a[0]是指向数组第一个元素的指针;
请注意这个指针(即&a[0])所指的地址正好是数组名本身的值,但是请不要混淆数组名(即1.1中的a)与数组第一个元素(即1.1中a[0])的地址,尽管他们看起来值是一样的实际上他们有区别,你将会在二维数组中看到。
我们能改变数组名的值吗?不妨来试一试:
//例子1.2
#include<stdio.h>
int main()
{
int a[10];
int b[10];
//指针c取得了b[0]的地址
int *c=&b[0];
//执行赋值
a=c;
}
编译器发出了警告,操作不可完成。
![](https://i-blog.csdnimg.cn/blog_migrate/38b489a29ab621c0d90141f796d2a478.png)
编译器告诉我们表达式a=c中左值应当是可修改的(即a的值是可修改的),实际上我们提到过数组名是指针常量,不能被修改!因此上述表达式是非法的!
因此 a=b 这样的操作也是非法的,我们也可以尝试着这样来理解为什么它是非法的:
数组名a代表了一个数组,b也代表了一个数组,你不能使用赋值符将一个数组的所有元素复制到另一个新的数组中。
既然数组名不能被修改,它能做什么,下一节给出了下标引用;
2.下标引用
在例子1.1中我们声明了数组a[10],并且了解到a是数组名,是不可修改的指针常量。请考虑下面的表达式是什么含义?
*(a+2)
表达式中有(a+2),对指针做加法意义何在?
写一个程序试试:
//例子2.1
#include<stdio.h>
int main()
{
int a[10];
//分别显示a与a+1的地址
printf("a =%p\n",a);
printf("a+1=%p\n",a+1);
return 0;
}
结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/ee9a541d5bb503598062c4b1c56dc435.png)
尽管地址是用16进制表示的但是上下两值的差值为4;4不正好就是sizeof(int)的值吗,即整形所占的字节数。字符串数组也是这样吗?修改一下程序再试试:
![](https://i-blog.csdnimg.cn/blog_migrate/d192ce8b69a2b6a44e64b29b8bcb9c46.png)
数组是一片连续的空间,(a+1)正好移动了本类型的一个单位,这是间接操作的手法。
回到最开始的*(a+2)来看更多的例子:
![](https://i-blog.csdnimg.cn/blog_migrate/1b1150cfa564bb13b686d122a9e1b585.png)
现在你能明白*(a+2)的含义了吗。对数组名加2找到了第三个数组元素(数组下标从0开始计数),* 号是间接访问操作,*(a+2)就表示的是a[2]的值。
*a+2 是什么
间接操作符 * 仅仅对a进行了操作实际上就是*(a+0),于是*a+2就是a[0]+2的值。
你也会看见这样的表达式:
&a
这个表达式是合法的,a是一个指针常量,对a取地址就是对指针取地址,因为计算机内存分配是不可预测的我们不会知道这个表达式的值。对指针取地址这件事情我们会在指向指针的指针中见到,那时候它会很有用处。
[参考书目]
《C语言与指针》[美]Kenneth A.Reek 著.人民邮电出版社.