栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

2.指针与数组1

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2.指针与数组1

先来看这样一个例子,这里出现了指针来引用数组的操作

//输入十个数,从大到小输出
#include
void sort(int x[],int n);
int main(void){
    int i,*p,a[10];
    p=a;     //取地址
    for(i=0;i<10;i++)
      scanf("%d",p++);//连续输入
      p=a;      //重新取地址
      sort(p,10);//函数引用
    for(p=a,i=0;i<10;i++)//连续输出
       { printf("%d",*p);
          p++;
        }
     printf("n");
     return 0;
 }
void sort(int x[],int n){
   int t;//空变量
   for(int i=0;i 

我们知道,数组里面每一个元素都有自己的地址,利用指针,可以很快地实现数组元素的引用

上面的例子中是一个较为简单的一维数组,先让p=a,(p=&a)要引用下一个元素,只需p++,这样相当于地址加一,自然可以取到下一个元素的地址,好,那么我们再看一下这种表达式

#include
int main(void) {
	int a[] = { 1,2,3,4 };
	printf("%d", *a);
	return 0;
}
//*a=*&a

很明显,这里的数组名前加了*,因为数组名代表第一个元素的地址 ,所以加*,变打出了第一个元素的值,即*a=*&a

再来看下面的表达式

t=*(x+j);*(x+j)=*(x+j+1);*(x+j+1)=t; 

这里与例子中表达式的作用一样,可以看到x[j]=*(x+j),数组中第j个元素可以用指针来表示,可以这么理解,x是数组的首地址,为0,假如j=3,x[2]是数组中第三个元素的值,(x+2)是第三个元素的地址,再加"*"取值,两式相等。

上面我们简单看了一下一个一维数组的指针应用,好,接下来看一下多维数组

int a[][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};

定义了一个三行四列的二维数组

二维数组里每一个元素的地址怎么用指针表示?

举例:找5,第一行第三个

#include
int main(void) {
	int a[][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };
	
	printf("%d",*(*(a+0)+2 ));//a[0][2] *(a[0]+2 )
	return 0;
}

可以看到*(*(a+0)+2)=*(a[0]+2)=a[0][2]

a[0][2]不必过多解释,就是数组的一般方法

*(a[0]+2) a[0]是第一行的首地址,+2就是列变化,往右移动2个地址,也就是第三个元素的地址

*(*(a+0)+2) 先看*(a+0),是a第一行的首地址+0,行变换+0,也就是第一行的首地址,再+2,就是第一行第三个元素的首地址

printf("%d", *(*(a + 1)+2));

像这样输出的结果是13,因为*(a+1)是行+1,也就是第二行的首地址

我们可以得出这样一个标准形式:*(*(a+i)+j) 这里面,+i就是在做行变化,+j就是在做列变化,可以这样来找到二维数组中每一个元素的地址

如果不便理解,这里有转换记忆的公式:

*(*(a+i)+j) ==*(*&a[i]+j)==*(a[i]+j)==*&a[i][j]==a[i][j]

好,大家思考一下下面这些表达式的输出结果是什么

#include
int main(void) {
	int a[][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };
	
	printf("%d,%dn", a,*a );
	printf("%d,%dn", a[0], *(a+0));
	printf("%d,%dn", &a[0], &a[0][0]);
	printf("%d,%dn", a[1], a+1);
	printf("%d,%dn", &a[1][0], *(a+1)+0);
	printf("%d,%dn", a[2], *(a+2));
	printf("%d,%dn", &a[2], a+2);
	printf("%d,%dn", a[1][0], *(*(a+1)+0));
	printf("%d,%dn", *a[2], *(*(a+2)+0));
	return 0;
}

答案:

 我们逐一分析:(首先明确a在定义时是这样的:a[][4])

1.a是数组的首地址,打出的是地址,是随机值,*a可不是取首地址中的值,*a就是a首地址的值,所以输出结果也是随机值

2.a[0]是地址 *a[0]才是地址中的值,*(a+0)=*a,同上

3.&a[0]也是地址,&a[0][0],a[0][0]是正确的写法,可是前面加个&相当于再次取了地址

4.a+1很明显是地址的加减,即a[0]+1=&a[0][1]

5-7.道理同上

8.前文标准方法

9.*a[2]=*(a[2]+0),即第三行首地址中的值

我们一定要熟知这些表达式所代表的意义,不然在之后看代码,打代码的操作中吃亏,考试也考不好(别问我怎么知道的)

好,接下来小试牛刀

通过指针引用多维数组示例一:

#include
int main(void) {
	int a[][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);//4是宽度,要求对齐
	}

	return 0;
}

结果:

 上面利用一个指针输出了数组的全部元素,要是要准确输出某一行某一列的元素,我们要利用数组指针,看这个例子:

#include
int main(void) {
	int a[][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };
	int (*p)[4],i,j;//定义数组指针(*p)[4]
	p = a;
	scanf("%d%d", &i, &j);
	printf("%d", *(*(p + i) + j));
	return 0;
}

p是一个指向有四个整型元素的数组的指针,很多初学者(我)搞不清什么指针,数组指针,指针数组,别急,试一试,想一想

下面是一个错误的代码

#include
int main(void) {
	int a[][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };
	int *p,i,j;
	p = a;
	scanf("%d%d", &i, &j);
	printf("%d", *(*(p + i) + j));
	return 0;
}

报错显示

 

 仔细想一想,指针,数组之间的关系,数组名是一个指针,上面的代码完全可以这样:

#include
int main(void) {
	int a[][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };
	int i,j;
	scanf("%d%d", &i, &j);
	printf("%d", *(*(a + i) + j));
	return 0;
}

而现在,要求用指针去引用,我只定义一个*p这样的指针,令p=a,这样,p相当于一个一维数组,用它来引用应该是这样的:

#include
int main(void) {
	int a[][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };
	int i,*p;
	p = a;
	scanf("%d", &i);
	printf("%d", *(p+i));
	return 0;
}

如果我要找21这个数,我要输入10,才能输出21,这就达不到几行几列这样的要求,所以我们现在应该明白:数组指针对应的是二维数组

上面用的是数组指针,也就是(*p)[4],是个指针

下面用到指针数组,*p[4],是个数组

(上面(*p)[4],*p[4]的不同本质是优先级()>[ ]>*)

#include
int main(void) {
	int a[] = { 100,200,300 };
	int i, *p[3];//定义指针数组*p[3]
	for (i = 0; i < 3; i++)
		p[i] = &a[i];
	for (i = 0; i < 3; i++)
		printf("a[%d]=%dn", i, *p[i]);

	return 0;
}

这算是一个最简单的指针数组的例子,初看这个代码,可能有人会问,这个定义的p什么玩意,不就是个数组吗,然后把数组a中的元素给了p,不对不对,指针数组中的每一个元素都是指针类型,这叫什么,不是一家人不进一家门,这一屋里全是指针类型的,于是p[i] = &a[i];就是把a中某元素的地址给了一个指针,哦,到这你就明白了,这不就是指针最原始的样子吗,把地址给它而已,然后,*p[i]就是把这个指针所指向地址里的元素的值打印出来。

再来看一个char类型的指针数组

#include
int main(void) {
	char* name[] = { "a","b","c","d" };
	for (int i = 0; i < 4; i++) {
		printf("name[%d]=%sn", i, name[i]);	
	}
	return 0;
}

输出结果:

 好,我们要注意,char类型,一个字符占一个字节,int 类型,一个占4字节,在这里i每次加一name[i]取的是每一个字符的首地址也就是说,我把a,b,c,d换成长一点的单词,打印出来的是那四个单词

 接下来我们再看加入函数后的例子:

//这是三个同学的四科成绩,要求打印三个人所有成绩的平均值,并打印第三个学生的四科成绩
#include
void average(float* p, int n);//声明函数
void search(float(*p)[4], int n);
int main(void) {
	float score[][4] = { {65,66,70,60},{80,87,90,81},{90,99,100,98} };
	average(*score, 12);//引用函数
	search(score, 2);
	return 0;
}
void average(float* p, int n) {
	float* p_end;
	float sum = 0, aver;
	p_end = p + n - 1;//在main函数中n=12,一共十二项成绩,在main函数中p就是score,这里是首地址,因为本身就占了一项,所以要-1
	for (; p <= p_end; p++)
		sum = sum + (*p);//把所有成绩加起来
	aver = sum / n;//求平均值
	printf("average=%5.2fn", aver);//保留两位小数
}
void search(float(*p)[4], int n) {
	for (int i = 0; i < 4; i++)//打印这个学生的四科成绩
		printf("%5.2f ", *(*(p + n) + i));//这里就是标准的引用方法,上文已经重点强调
	printf("n");
}

打印结果:

 好,这一章就讲到这里,如有疏漏,错误,还请指正,谢谢。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/629088.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号