【补习】二维数组,指针,函数

学习链表的时候一脸懵逼,发现需要从二维数组与指针开始补习,从零开始的代码学习笔记第一篇,希望今后也能坚持下去。

——————————————————————————————————

 

一、辨析数组形式的含义

定义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语言程序设计》科学出版社


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值