指针与二维数组
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
我们以为,二维数组的存储形式是:
但是,二维数组实际上是以一维数组为单位连续存储的。
这样,上述的二维数组就可以看成是“特殊的”一维数组了。
而数组名a是这个“特殊的”一维数组的名称,也就是首地址(常量地址),也就是第一个元素的地址。
也就是第一行的首地址,是指首行一整行,并不是指某个具体元素。
对于这种,我们称之为“行指针”。同理:a+0,a+1,a+2,都是行指针。
接下来,我们来放大观看首行,首行的元素分别是:a[0][0],a[0][1],a[0][2],a[0][3]。
将其看作一个独立的一维数组,那么 a[0]就是这个数组的名称,也就是这个数组的首地址。
也就是第一个元素的地址,也就是a[0]+0。a[0]和a[0]+0都是指具体的元素。
对于这种,我们称之为“列指针”。
由上面的比较可以得出:
行指针:指向某一行,不指向具体的元素。
列指针:指向行中具体的元素。
也就是说,列指针只要在同一行,不管它们指向行中的哪个元素,它们的行地址都是在同一行的地址,所以它们的行地址都是一样的。
所以,&列指针--->行指针
相反地可以推出:
*行指针---->列指针
对于元素a[1][2],其地址用列指针表示为a[1]+2,等价表示为*(a+1)+2,那么内容是*(*(a+1)+2);
那么如何声明行指针呢?
对于数组a[3][4],可以这样声明(并初始化)行指针:
int (*ptr)[4]=a; //注意行指针是一行中所有元素所共有的,所以应该等于列数
由上面可知:
行指针-->列指针:
a+i --> *(a+i) --> a[i] -->*a[i] ([]优先级大于*)
这里还要注意:
声明和初始化列指针时,要注意“*”如:
int *ptr=*a;//true int *ptr=a; //error
下面是应用:
#include<stdio.h> /** 三个学生修四门功课,求总平均分,输出第n个学生成绩 */ void average(float *p, int n); void search(float (*p)[4], int n); int main() { float score[3][4] = {{20,30,40,50},{25,35,45,55},{60,70,80,90}}; average(*score,12); //*score为列指针 search(score,2); //score为行指针 return 0; } void average(float *p, int n) { float *p_end,sum=0,aver; p_end = p+n-1; for(;p<p_end;p++) sum=sum+(*p); aver=sum/n; printf("average=%5.2f\n",aver); } void search(float (*p)[4], int n) { int i; printf("No.%d :\n",n); for(i=0;i<4;i++) printf("%5.2f ",*(*(p+n)+i)); }
本文稍有借鉴:https://blog.csdn.net/haussuden/article/details/5965304
以及:https://wenku.baidu.com/view/acf838ef856a561252d36fe3.html
有不足之处,欢迎指出。