指向一维数组的指针变量定义:

如果定义一个指针变量,使其指向一个一维数组的首地址,或指向某个数组元素的地址,则称该指针变量为指向一维数组的指针变量。
代码实例:

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
int a[10],*p;//首先对他们的类型做一个定义
p=a;
p=&a[0];//这两种规定都是符合的。
return 0;
}

以上这个是指向数组的首地址输出的都只是a[0]的值。
对于上面所写&a[i]的表示形式,由于数组元素访问运算符[]的优先级更高,所以这里不必写成&(a[i])点形式。
插入优先级排序:由高到低为:!,算术运算符,关系运算符,&&,||,赋值运算符。

可以得到数组元素a[i]地址的方式有四种 接下来,我就只会用代码来介绍常用的三种。

‌第一种是通过数组的下标来引用数组元素,这也是我们之前学数组时一直用的方法,这里就不过多介绍了,如下所示:

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
int main()
{
int i;
int a[10]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
printf("%5d",a[i]);
}
return 0;
}

‌第二种是可以通过数组名来访问数组元素。例如:* (a+i)与a[i]等价。

注意:使用数组名时,不能用a++的方式,因为在这里的a是地址常量,而常量不能被重新赋值。
实例:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>

int main()
{
int i;
int a[10]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
printf("%5d",*(a+i));
}
return 0;
}

‌第三种,如果定义了指针变量p(int p;),并使p指向数组a的首地址(即p=a),则可以用指针变量来访问数组元素元素,(p+0)(即(p))与a[0]等价~~~~(p+i)与a[i]等价。

实例:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int main()
{
int i;
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p; p=a;
for(i=0;i<10;i++){
printf("%5d",*(p+i));
}
return 0;
}

例题,使用指向数组的指针变量,计算数组元素的平均值。

提示:定义数组和指针变量后,让指针变量指向数组,循环求和。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>

int main()
{
int a[10],*p,k;
float aver=0;
p=a;
for(k=0;k<10;k++)
{
scanf("%d",p+k); /*p+k等价于&a[k]*/
aver=aver+*(p+k); /* *(p+k)等价于a[k]*/
}
aver=aver/10;
for(k=0;k<10;k++)
printf("%d\t",*(p+k)); /* *(p+k)等价于a[k] */
printf("\n平均值=%f\n",aver);
return 0;
}

在该程序运行过程中,指针变量p的值不变化。接下来我将为你们展示我另一种指针变量p的值发生变化的答案。

程序代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>

int main()
{
int a[10],*p=a,i;
float aver=0;
for(i=0;i<10;i++,p++)
{
scanf("%d",p); /*p+k等价于&a[k]*/
aver=aver+*(p); /* *(p+k)等价于a[k]*/
}
aver=aver/10;
p=a;
for(i=0;i<10;i++,p++)
printf("%d\t",*(p)); /* *(p+k)等价于a[k] */
printf("\n平均值=%f\n",aver);
return 0;
}

注意:在这个程序使用第二个for循环输出数组元素的值(即 p, p与a[i等价]之前,一定要让指针变量p重新指向数组的第一个元素(即执行语句“p=a;”),否则会出错。**
从上面两个程序可以看出:使用指针变量p引用数组元素时,既可以用p+i方式,也可以用p++方式。用p+i方式时,p的值不变(p中存放数组首地址)。用p++方式时,p的初值是数组首地址(a[0]的地址),后续按顺序取其它数组元素的地址。这两种方式都可以按顺序访问数组的每个元素。

指针使用的几个小细节:

〈1〉指针初始化。

在定义指针变量时,可以用合法的指针值对它进行初始化。例如:

1
2
3
4
5
6
#include <stdio.h>
int main()
{
int n, * p = &n;
return 0;
}

<2>空指针

空指针是一个特殊的值,也是唯一一个对任何指针类型都合法的值。一个指针变量具有空值,表示它当时没有被赋予有意义的地址,处于闲置状态。

空指针值用0表示。将空值赋予一个指针变量,说明该指针变量不再是一个不确定的值,而是一个有效的值。

为了提高程序的可读性,C语言标准库定义了一个与0等价的符号常量NULL,当p是一个指针变量时,在程序中有两种形式:

1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
int n, * p = &n;
p = NULL;//第一种
p = 0;//第二种
return 0;
}

这两种写法都是将指针p放置为空指针值,前一种写法使读该程序的人容易意识到这里是一个指针赋值。采用前一种写法时,必须通过#include <stdio.h>包含相应的标准头文件。

<3>如果指针变量p指向数组a的元素a[i](即p=&a[i]),则需要注意以下几点:

  1. *(p–)相当于a[i–],先取 *p,再使p减1。

  2. *(++p)相当于a[++i],先使p加1,再取 *p。

  3. *(–p)相当于a[–i],先使p减1,再取 *p。

<4>如果指针变量p指向数组a的首地址(即p=a),则需要注意以下几点:

  1. 执行p++(或p+=1)后,p指向数组的下一个元素。
  2. *p++相当于 *(p++)。因为 *和++的优先级相同,++是右结合运算符。
  3. *(p++)与 *(++p)的作用不同。 *(p++)为先取 *p,再使p加1; *(++p)为先使p加1,再取 *p。
  4. (p)++表示p指向的数组元素的值加1。//这个可别学懵逼了*

<5>当两个指针变量指向同一个数组时,可以求他们的差,得到的结果是对应的两个数组元素的下标之差(可能时负整数)。当指向的不是同一个数组时,对他们的比较将毫无意义。