通过指针引用数组

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;
}

运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值