1.数组元素的指针
可以用一个指针变量指向一个数组元素。例如:
int a[10] = { 1,3,5,7,9,11,13,15,17,19 };
int* p;
p = &a[0];
以上是是指针变量p指向a数组的第0号元素。
引用数组元素可以用下标法,也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量更高(占内存少,运行速度更快)。
在C语言中,数组名(不包括形参数组名)代表数组中首元素(即序号为0的元素)的地址。以下语句等价
p = &a[0];
p = a;
在定义指针变量时可以对它初始化,如:
int *p=&a[0];
等效以下代码
int*p=a;
它的作用是将a数组首元素的地址赋给指针变量p。
2.在引用数组元素时指针的运算
在指针指向一个数组元素时,可以对指针进行以下运算:
加一个整数(用+或+=),如p+1(指向同数组的下一个元素);
减一个整数(用-或-=),如p-1(指向同数组的上一个元素);
自加运算,如p++,++p;
自减运算,如p--,--p;
两个指针相减,如p1-p2(只有p1和p2都指向同一数组中的元素才有意义)
1.如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址,或者说,它们指向a数组序号为i的元素。这里需要注意的是a代表数组首元素的地址,a+1也是地址, 它的计算方法同p+1,即它的实际地址为a+1xd。例如, p+9和a+9的值是&a[9],它指向a[9]。
*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即a[i]。例如,*(p+5)或*(a+5)就是a[5]。即:*(p+ 5),*(a+5)和a[5]三者等价。
2."[]"实际上是变值运算符,即将a[i]按a+i计算地址,然后找出地址单元中的值。
3.如果指针变量pl和p2都指向同一数组中的元素,如执行p2-pl,结果是p2-p1 的值(两个地址之差)除以数组元素的长度。假设,p2指向实型数组元素a[5],p2的值为2020;pl指向a[3],其值为2012,则p2-pl的结果是(2020-2012)/4=2。这个结果是有意义的,表示p2所指的元素与p1所指的元素之间差2个元素。这样,人们就不需要具体地知道pl和p2的值,然后去计算它们的相对位置,而是直接用p2-p1就可知道它们所指元素的相对距离。
注意:两个地址不能相加,如p1+p2是无实际意义的。
3.通过指针引用数组元素
例题1:有一个整型数组a,有10个元素,要求输出数组中的全部元素。
解题思路:引用数组个元素的值有3种方法:(1)下标法,如a[3];(2)通过数组名计算数组元素地址,找出元素的值(3)用指针变量指向数组元素。
(1)下标法
#include<stdio.h>
int main()
{
int a[10];
int i;
printf("请输入10个整数:");
for (i = 0; i < 10; i++)
scanf("%d",a+i);
for (i = 0; i < 10; i++)
printf(" %d", a[i]);
printf("\n");
return 0;
}
(2)通过数组名计算数组元素地址,找出元素的值
#include<stdio.h>
int main()
{
int a[10];
int i;
printf("请输入10个整数:");
for (i = 0; i < 10; i++)
scanf("%d",a+i);
for (i = 0; i < 10; i++)
printf(" %d", *(a+i));
printf("\n");
return 0;
}
(3)用指针变量指向数组元素。
#include<stdio.h>
int main()
{
int a[10];
int *p, i;
printf("请输入10个整数:");
for (i = 0; i < 10; i++)
scanf("%d",a+i);
for (p=a;p<(a+10);p++)
printf(" %d", *p);
printf("\n");
return 0;
}
注意:在使用指针变量指向数组元素时
(1)可以通过改变指针变量的值指向不同的元素。
(2)要注意指针变量的当前值。
例题2:通过指针变量输出整型变量a的10个元素
解题思路:用指针变量p指向数组元素,通过改变指针变量的值,使p先后指向a[0]~a[9]各元素。
#include<stdio.h>
int main()
{
int a[10];
int *p, i;
p = a;
printf("请输入10个整数:");
for (i = 0; i < 10; i++)
scanf("%d", p++);
p = a;
for (i = 0; i < 10; i++, p++)
printf("%d ", *p);
printf("\n");
return 0;
}
4.用数组名作函数参数
实参类型 | 变量名 | 数组名 |
要求形参的类型 | 变量名 | 数组名或指针变量 |
传递的信息 | 变量的值 | 实参数组首元素的地址 |
通过函数调用能否改变实参的值 | 不能改变实参变量的值 | 能改变实参数组的值 |
注意:实参数组名代表一个固定的地址,或者说指针变量,但形参数组名并不是一个固定的地址,而是按指针变量处理。
例题3:将数组中n个整数按相反顺序排放
#include<stdio.h>
int main()
{
void inv(int x[], int n);
int i, a[10] = { 0,1,2,3,4,5,6,7,8,9 };
printf("原始数组:\n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
inv(a, 10);
printf("交换后的数组:\n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
void inv(int x[], int n)
{int temp, i, j, m = (n - 1) / 2;
for (i = 0; i <= m; i++)
{
j = n - 1 - i;
temp = x[i]; x[i] = x[j]; x[j] = temp;
}
return;
}
运行结果如下:
对这个程序可以做一些改动,将函数inv中的形参x改为指针变量。相应的实参仍为数组名a,即数组a首元素的地址,将它传给形参指针变量x,这是x就指向a[0]。i的初值为x,j的初值为x+n-1,使*i与*j交换就是使a[i]与a[j]交换。
#include<stdio.h>
int main()
{
void inv(int* x, int n);
int i, a[10] = {0,1,2,3,4,5,6,7,8,9};
printf("原始数组为:\n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
inv(a, 10);
printf("按相反顺序排放后数组顺序为:\n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
return 0;
}
void inv(int* x, int n)
{
int* p, * i, * j, temp, m = (n - 1) / 2;
i = x;
j = x + n-1;
p = x + m;
for (; i <= p; i++, j--)
{
temp = *i;
*i = *j;
*j = temp;
}
return;
}
例题4:用指针方法对10个整数按由大到小顺序排列
#include<stdio.h>
int main()
{
void sort(int x[10], int n);
int i, a[10];
printf("请输入10个整数:");
for (i = 0; i < 10; i++)
scanf("%d ", &a[i]);
sort(a, 10);
printf("\n");
printf("从大到小排序后的顺序为:");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
void sort(int x[], int n)
{
int i, j, k, t;
for (i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
if (x[j] > x[k])
k = j;
if (k != i)
{
t = x[i];
x[i] = x[k];
x[k] = t;
}
}
5.通过指针引用多维数组
例题5:输出二维数组地址和元素的值
#include<stdio.h>
int main()
{
int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21 };
printf("%d,%d\n", a, *a);//0行起始地址和0行0列元素地址
printf("%d,%d\n", a[0],*(a+0)); //0行0列元素地址
printf("%d,%d\n", &a[0],&a[0][0]);;//0行起始地址和0行0列元素地址
printf("%d,%d\n", a[1], a+1);//1行0列元素地址和1行起始地址
printf("%d,%d\n", &a[1][0],*(a+1)+0);//1行0列元素地址
printf("%d,%d\n", a[2],*(a+2));//2行起始地址
printf("%d,%d\n", a[1][0],*(*(a+1)+0));//1行0列元素的值
printf("%d,%d\n", *a[2],*(*(a+2)+0));//2行0列元素的值
return 0;
}
运行结果如下:
注意:在不同的计算机、不同的编译环境。不同的时间运行以上程序时,由于分配内存的情况不同,所显示的地址可能是不同的。
例题6:有个3x4的二维数组,要求用指向元素的指针变量输出二维数组各元素的值。
#include<stdio.h>
int main()
{
int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21,23 };
int* p;
for (p = a[0]; p < a[0] + 12; p++)
{
if ((p - a[0]) % 4 == 0)
printf("\n");
printf("%4d", *p);
}
printf("\n");
return 0;
}
运行结果如下: