![000d6cb87fc4103a3f99bc273887992b.png](https://i-blog.csdnimg.cn/blog_migrate/d9f8c92c9d5cf596360b2610112f58d3.jpeg)
在C语言中,指针和数组是相互关联的。
首先,指针的算术运算和关系运算常常是针对指针数组中的元素而言的。由于数组在内存中是连续存放的,因此指向同一数组中不同元素的两个指针的关系运算常用于比较它们所指元素在数组中的前后位置的关系。指针的算术运算则常用于移动指针的指向,使其指向数组中的其它元素。当然,仅当指针的算术运算结果仍然指向同一数组中的元素时才有意义。
其次,指针和数组的关系还表现在:在表达式中,数组名被自动转化为指向数组中的第一个元素的常量指针(除用作sizeof运算的操作数外)。例如:
int a[100];
int *p;
p=a;
因为a被自动转换为指向a[0]的一个int型常量指针,所以经p=a赋值后,p也指向了a[0]。
最后,数组的下标运算符[]实际上是以一个指针作为其操作数。例如,数组元素a[i]被编译器解释为表达式*(a+i),表示从数组首地址开始向后移动i个元素并取出其内容,而&a[i]表示取数组a的第i+1个元素的地址,它等价于指针表达式a+i。因此,数组元素可以通过指针来引用,指针也可以用下标形式来表示。可用数组实现的操作也可用指针来实现。只是指针实现比数组实现的效率高,而数组实现方法更容易理解。
![cc10e0ab145abf43d87a6db68d1ad800.png](https://i-blog.csdnimg.cn/blog_migrate/6ea0b0e002f36e46ea6ab9b0baeb1153.jpeg)
一、一维数组的地址和指针
1.一维数组的指针概念
由于数组元素在内存中是连续存放的,即在内存中占用一段连续的存储单元,每个数组元素占用其中的一个存储单元。因此,数组元素实质上就是一个变量,数组元素的指针就是该元素在内存中所占存储单元的首地址,而一维数组的指针就是数组中各元素所占连续存储单元的起始地址,即第一个元素的指针。例如:
定义了一个有3个短整型元素的一维数组a,如图1-1所示,因为数组a的每个元素在内存中占2个字节的内存,所以有3个元素的数组a在内存中总计占10个字节的连续的存储单元,其起始地址可通过&a来得到。因为数组名a代表数组的首地址,即元素a[0]的地址(&a[0]),所以要定义一个指向一维短整型数组的指针变量p,并使其指向数组a的首地址,可用如下的变量语句:
short *p=a;
则相当于语句:
short *p=&a[0];
![a6cf6b3b8c86e54830be56480cc0419e.png](https://i-blog.csdnimg.cn/blog_migrate/0e61828b9af6ecd73dea0fdfade71d0e.jpeg)
图1—1 一维数组的地址示意图
2.一维数组的指针引用一维数组元素
既然数组名a代表数组的首地址(即&a[0]),那么表达式a+1就表示首地址后面的下一个元素的地址,即&a[1]。由此可见,表达式a+i代表数组中下标为i的元素a[i]的地址(&a[i]).。
不仅可以通过下标方式来引用数组中的元素,还可以通过使用间接寻址运算符*来引用数组的元素。例如,*a表示取出首地址a所指存储单元中的内容,即元素a[0],*(a+i)表示取出首地址元素后面第i个元素的内容,即下标为i的元素a[i]。
此外,还可以通过指向一维数组的指针变量p来引用数组a中的元素,如图1-2所示。
![34e5db90b982be4cd52b7ab566a9726c.png](https://i-blog.csdnimg.cn/blog_migrate/744853397fdf174043d2cfe13cefae37.jpeg)
图1-2 指针运算和数组的关系
当指针变量p指向数组的首地址&a[0]时,*p就表示取出p所指单元即元素a[0]的值,此外,由于p+i代表当前指针所指元素后面的第i个元素的地址,因此*(p+i)表示取出p+i所指向的存储单元内容,即元素a[i]的值。*(p+i)也可以用它的下标形式p[i]来表示。
与通过*(a+i)来引用数组元素a[i]不同的是,由于指针变量p不一定永远都指向数组的首地址&a[0],因为仅当指针变量p指向数组的首地址&a[0]时,*(p+i)才是对a[i]的引用。否则,如果通过增1运算改变指针变量p的指向,使p直接指向a[i],那么就是对a[i]的引用了。
此外,需要注意的是,在传统的算术中,1000+1的结果是1001,但是对于指针的算术就不是这样了。当给指针加上一个整数或者从指针中减去一个整数时,并非简单地增减这个整数值,而是这个整数值乘以指针所指向对象的字节长度。这个字节长度取决于指针所指向的对象的数据类型。不过,当对一个字符数组执行的指针算术运算时,运算的结果和普通的算术运算的结果是不一样的,因为每个字符只占1字节。
小贴士:
1)数组名a是一个地址常量,不能通过赋值操作改变它的值,指针变量p是一个变量,可以通过赋值运算改变它的值,从而使p指向数组中的其它元素
2)虽然p+1和p++都指向当前指针所指单元的下一个元素,但p+1并不改变当前指针的指向,p仍然指向原来所指向的元素,而p++相当于执行p=p+1,因此p++操作改变了指针p的指向,表示将指针变量p向前移动使其指向了下一个元素。
3)p+1并非将指针变量p的值简单地增加1字节,事实上,它是增加了1*sizeof(指针的基类型)字节
4)指针的算术运算仅在作用于数组时才有意义。因为不能假设同一数据类型的两个变量在内存中相邻存储的,除非它们是数组中的两个相邻的元素。同理,对并非指向同一数组的元素的两个指针进行相减运算,也是无意义的。
如下有五种输入/输出数组元素的方法:
方法1 用下标法直接引用数组元素
int a[10],i;
for(i=0;i<10;i++)
{
scanf("%d