1、指向数组元素的指针变量
- #include<stdio.h>
- int main()
- {
- int* p;
- int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
- int i, j;
- //将第0行第0列的地址赋给p
- for (p = a[0]; p < a[0] + 12; p++)//注意是a[0]
- {
- if ((p - a[0]) % 4 == 0)
- printf("\n");
- printf("%-4d", *p);
- }
- printf("\n");
- return 0;
- }
上述是由int*实现的,现在我们可以使p指向的不是整型变量,而是指向包含m个元素的一维数组,这时,如果p先指向a[0],那么p+1就不是指向a[0][1],而是指向a[1],p的增长以一维数组的长度为单位。
2、指向由m个元素组成的一维数组的指针变量
数据类型:(*p)[m]
功能:指定变量p是一个指针变量,它指向包含m个元素的一维数组
例如:int(*p)[4];
p=a;
p指向a数组,p++的值为a+1,只能对行进行操作,不能对行中的某个元素进行操作,只有执行*(a++)将行转列后,才能对数组元素进行操作
程序:输出二维数组任意一行任意一列元素的值
- #include<stdio.h>
- int main()
- {
- int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
- int(*p)[4];//p指向包含4个整型的一位数组
- int i, j;
- p = a;//将二维数组首地址赋给p
- scanf_s("%d%d", &i, &j);
- printf("a[%d][%d]=%d", i, j, *( * (p + i) + j));
- return 0;
- }
注意,此时p已经指向了一维数组,因此(p+i)指向的是a[i],*(p+i)就是a[i][0]的地址,加上j就是a[i][j]的地址
分析:指针变量p指向包含4个整形的一维数组,p+i表示第i行首地址,在二维数组中,*(p+i)表示第i行第0列的元素的地址,即p[i],此时将行指针转化为列指针,则*(p+i)+j 表示第i行第j列元素的地址,即p[i]+j,而*(*(p+i)+j)代表第i行第j列元素的值
如果对一维数组使用此类型会有怎样的结果?分析以下程序:
- #include<stdio.h>
- int main()
- {
- int a[4] = { 1,3,5,7 };
- int(*p)[4];
- p = &a;
- printf("%d\n", (*p)[3]);
- return 0;
- }
输出结果为a[3]即7.
注意第6行不应写成“p=a;”,因为这样写表示p的值是&a[0],指向首元素a[0].“p=&a;”表示 p指向一维数组(行),(* p)[3]是p所指向的行中序号为3的元素。
总结:要注意指针变量的类型,从“int( * p)[4];”可以看到,p的类型不是int *型,而是int( *)[4]型,p被定义为指向一维整型数组的指针变量,一维数组有4个元素,因此p的基类型是一维数组,其长度是16字节。
“*(p+2)+3”括号中的2是以p的基类型(一维整型数组)的长度为单位的,即p每加1,地址就增加16个字节(4个元素,每个元素4个字节),而“*(p+2)+3”括号外的数字3,不是以p的基类型的长度为单位的。由于经过*(p十2)的运算,得到a[2],即&a[2][0],它已经转化为指向列元素的指针了,因此加3是以元素的长度为单位的,加3就是加(3×4)个字节。虽然 p+2和*(p+2)具有相同的值,但由于它们所指向的对象的长度不同,因此(p+2)+3和*(p+2)+3的值就不相同了。
3.用指向数组的指针作函数参数
一维数组名可以作为函数参数,多维数组名也可作函数参数。用指针变量作形参,以接受实参数组名传递来的地址。可以有两种方法:①用指向变量的指针变量﹔②用指向一维数组的指针变量。
程序:有一个班,3个学生,各学4门课,计算总平均分数以及第n个学生的成绩。
- #include<stdio.h>
- int main()
- {
- void ave(float* p, int m);
- void search(float(*p)[4], int n);
- float score[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
- int n;
- //这里的ave求元素不能用二维数组名,使用*将行形式变成列形式即&score[0][0]
- ave(*score, 12);//因为要求元素
- printf("enter 0~2:\n");
- scanf_s("%d", &n);
- search(score, n);//我要的形参就是行形式,直接写二维数组起始名
- return 0;
- }
- void ave(float* p, int m)
- {
- float sum=0, aver=0;
- //此时实参传递给p为&score[0][0],又变成了指针在一维数组中的应用
- float* b = p + m;
- for (; p < b; p++)
- {
- sum += *p;//在已经求了地址的基础上再求值
- }
- aver = sum / m;
- printf("the average is %f\n", aver);
-
- }
- void search(float(*p)[4], int n)
- {
- int i;
- for (i = 0; i < 4; i++)
- printf("%6.2f", *(*(p + n) + i));
- printf("\n");
- }
解析:在ave函数中定义为float*p,实参写为*score,即表示为score[0],也即&score[0][0],指针转换成了列形式,这样就可以利用程序先后指向数组中的每一个元素。
在search函数中定义为float(*p)[4],指向的不是单个元素,而是 带有4个整型的一维数组,注意,实参此时应该是二维数组名,因为我要的就是行形式,这样*(p+n)就表示&a[n],*(p+n)+i就表示&a[n][i]了