v 接着上一篇的数组、函数、指针,咱来继续总结一下函数与指针的一些知识点。上一次总结到了函数指针,接下来第一点就从什么是指针函数开始。
v 指针函数
顾名思义,这是一个函数,函数的返回值是指针(地址)。
Ø 定义指针型函数的一般形式为:
类型说明符 *函数名(形参表)
{
…… /*函数体*/
}
其中函数名之前加了“*”号表明这是一个指针型函数,即返回值是一个指针。类型说明符表示了返回的指针值所指向的数据类型。
v 总结:int(*p)()和 int *p()区别
1.int (*p)()是一个变量说明,说明p是一个指向函数入口的指针变量,该函数的返回值是整型量,(*p)的两边的括号不能少。
2. int *p()则不是变量说明而是函数说明,说明p是一个指针型函数,其返回值是一个指向整型量的指针,*p两边没有括号。作为函数说明,在括号内最好写入形式参数,这样便于与变量说明区别。
Ø 知识点应用:
在C语言的面试题当中,喜欢对数组、指针、函数都写成一个整体,以此来让区分面试者学习C语言的知识点掌握的如何。
下面来举两个例子:
提示:遇到这种题目,记住两个原则:1.从变量开始看 2.从变量开始向右看 。
1. int *(*(*fp)(int))[10];
分析:从变量fp开始看,fp是一个指针;指针右边是左括号,分析必然是函数。那么fp指针便指向这个函数,函数的形参是Int,返回值是指针;而这个指针又指向一个数组,数组里面有10个元素,每个元素都是int *型。
2. int *(*(*array[5])())();
分析:array是一个变量,向右看,是一个方括号,可见这是一个数组。数组里面有5个元素,每个元素都是指针类型;数组里面的指针指向一个函数,函数的形参为空,返回值为指针类型;这个指针又指向一个函数,函数的形参为空,返回值为Int *型。
Ps:这里面涉及到的数组、指针、函数。分析起来:
(1) 数组主要分析数组里面有几个元素,每个元素是什么数据类型
(2) 函数主要分析函数的形参、返回值
(3) 指针主要分析指向什么
总结:各种形式的步长(针对二维数组a[4][4])
1. &a:数组的首地址,步长为一个数组。故&a+1指向下一个数组的地址
2. a:数组的第0行的地址,步长为一行。故a+1为指向第一行的地址
3. a[0]:数组第0行第0列的地址,步长为一个元素。故a[0]+1为第0行第一个元素
注意:
1.不要把&a[i]简单的理解为a[i]的物理地址,因为并不存在a[i]这个变量。它只是一种地址的计算方法,能得到第i行的地址。
2.&a[i]和a[i]的值是一样的,但它的含义却不同。&a[i]或a+i指向行,而a[i]或*(a+i)指向列。当下标j=0时,&a[i]和a[i]+j的值相等。*(a+i)只是a[i]的另一种表示形式。在二维数组中,a+i=a[i]=*(a+i)=&a[i]=&a[i][0]即它们的地址值是相等的。
知识应用:
下面是一道又关于二位数组地址的面试题:
main()
{ int a[3][4]={{1,2,3,4},{3,4,5,6},{5,6,7,8}};
int i;
int (*p)[4]=a,*q=a[0];
for(i=0;i<3;i++)
{ if(i==0)
(*p)[i+i/2]=*q+1;
else
p++,++q;
}
for(i=0;i<3;i++)
printf("%d,",a[i][i]);
printf("%d,%d\n",*((int *)p),*q);
}
求printf中的结果:
2 4 7 3,5
这段程序的关键代码:
if(i==0)
(*p)[i+i/2]=*q+1;
else
p++,++q;
分析:(*p)即指向第0行的地址,(*q)指向第0列的地址
I = 0的时候,就是实现将原来第0列的数加一赋值给第0行地址里面的数据;当i!= 0的时候,p++,q++,就是实现将p(原来指向第0行)和q(原来指向第0列的地址)向后移动,根据条件,P和q向后移动两个位置,则p和q就分别指向了5和3.