学习链表的时候一脸懵逼,发现需要从二维数组与指针开始补习,从零开始的代码学习笔记第一篇,希望今后也能坚持下去。
——————————————————————————————————
一、辨析数组形式的含义
定义3行4列的二维数组a如下:
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
一个没什么特别的二维数组,我的学习目的是弄清楚a[0],a[2],a[3]对应一维数组的首地址的含义和指针基类型,分清不同表示形式的含义。
这个二维数组由三个一维数组组成,根据C标准的规定,a是指向第一个元素的指针,a=&a[0],所以:
a+i=&a[i]
a[i]=*(a+i)
a[0],a[1],a[3]是一维数组名,表示对应一维数组的首地址的指针,如a[0]是一维数组a[0][0],a[0][1],a[0][2],a[0][3]的首地址,其指针基类型为int型,所以以下等价成立:
a[0]=&a[0][0]
a[0]+1=&a[0][1]
a[1]+1=&a[1][1]
a[1]+2=&a[1][2]
分析可知,a向后移动1个储存单元,相当于移动了一个一维数组所有元素的存储位置,这个一维数组的元素个数就是数组a的列下表,因此二维数组名作为指针,其基类型是一维数组。对a而言其基类型是具有4个整型元素的一维数组。如果a数组的首地址是2000,a+1的值就是2000+4×sizeof(int)
总结:
a+i=&a[i]
a[i]+j=&a[i][j]
a[i][j]=* (&a[i][j])=* (a[i]+j)=* (*(&a[i])+j)=* (* (a+i)+j)
【二维数组a代表的不同含义】
a:二维数组首地址,第1行的首地址,基类型是一维数组的指针
a+i,&a[i]:第i+1行的首地址,基类型是一维数组的指针
*(a+i)+j,a[i]+j,&a[i][j]:第i+1行第j+1列的元素的地址,基类型是整型的指针
* (* (a+i)+j),a[i][j]:第i+1行第j+1 列的元素
其中a,a+1,&a[i]这些指向一维数组的指针习惯上称为行指针,而诸如a[i],a[i]+j,* (a+i),&a[i][j] 都是基类型与元素类型一致的指针,习惯上称为列指针。
两者可以互相转换,行指针通过加*运算变成列指针,列指针加&运算变成行指针。
二、指针与二维数组
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; int *p p=a; /*错误*/ p=a[i]; /*正确*/ p=*(a+1); /*正确*/ p=*(a+1)+2; /*正确*/
错误原因是基类型不匹配。
C语言提供了指向一维数组的指针(基类型为一维数组),定义格式为:
类型说明符(*指针变量名)长度;
注:①括号不能省略
②长度等于一维数组元素的个数;
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; int (*p)[4]; /*4与上面列的数值4相同*/ p=a; /*正确*/
用指针变量来取代a,该指针的基类型必须是具有4个元素的一维数组(因为数组a的列下标为4)
另外,二维数组元素的引用也可以用指针数组实现
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; int *p[3]={a[0],a[1],a[2]}; /*3与上面行的数值3相同,p[i]指向a[i]*/ int i,j; for(i=0;i<3;i++){ for(j=0;j<4;j++){ printf("%d",*(*(p+i)+j)); printf("\n"); }
三、指针与函数
1、指针作为实际参数
int fun(int *p){ …… }
2、返回指针值的指针型函数
int *fun(int x){ …… }
表示fun是一个返回指针值的指针型函数,它返回的指针指向一个整型变量
指针型函数返回的地址可以是实参中的指针,也可能是返回指向外部变量或指向声明为static的局部变量的指针,但是记住不要范围指向自动局部变量的指针,如下代码是错误的:
int *fun(void){ int i; …… return &i; }
因为一旦fun返回,变量i就不存在了,指向它的指针无效
3、函数指针变量
在C语言中,一个函数总是占用一段连续的内存区,而函数名就素该函数所占内存区的首地址,我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使改指针变量指向该函数,然后通过指针变量就可以找到并调用这个函数
(1)定义
类型说明符(*指针变量名)();
其中类型说明符表示被指函数的返回值的类型,空括号表示指针变量指向一个函数
(2)赋值
函数指针变量=函数名;
(3)调用
函数指针变量名(实参列表);或(*函数指针变量名)(实参列表);
四、总结
int *p:p为指向整型数据的指针变量
int **p:p为一个指向整型指针的指针变量
int *p[n]:p为指针数组,由n个指向整型数据的指针元素组成,n与原二维数组的行数相同
int (*p)[n]:p为指向含n个元素的一维数组的指针变量,n与原二维数组的列数相同
int *p(int i):p为返回整型指针的函数
int (*p)():p为指向返回整型值的函数指针
——————————————————————————————————
感觉搞清楚了很多东西,然而有些地方还是分不太清楚,可能需要在练习中巩固吧。开心,可以愉♂快地去学习链表了(不不是的
参考资料:《C语言程序设计》科学出版社
【补习】二维数组,指针,函数
最新推荐文章于 2022-08-31 11:35:02 发布