Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1068535
  • 博文数量: 139
  • 博客积分: 1823
  • 博客等级: 上尉
  • 技术积分: 3403
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-05 09:54
文章存档

2014年(7)

2013年(16)

2012年(48)

2011年(68)

分类: C/C++

2012-08-20 11:14:12

姑且这么叫吧,但《C和指针》这本书上把这些知识点叫做“高级声明”。

在看例子之前,需要强调,函数指针本质上是一个指针(函数的指针),它指向的是一个函数。而指针函数是一个函数(指针的函数),函数的返回值是一个指针

1. int  abc(int a)

2. int  abc[3]

3. int  **abc(int a)

4. int  (*abc)(int a)

5. int  (*abc)[6]

6. int  *abc(int a)

7. int  **(*abc[6])(int a)

8. int  **abc[6]

9. int  *(*abc)[6]

10. int  *(*abc(int a))(int a)

11. int  (*(*abc)(int a))(int a)

12. int  (**(*abc)(int a))(int a)

13. int  (*(*abc)(int a))[6]

14. int  *(*(*(*abc)(int a))[6])(int a)

 

解答

1.      返回值为int的函数。

2.      int 型数组

3.      返回值为“int 型指针的指针”的函数。()的优先级高于*(这里指右边的*),所以abc先和()结合,即abcint a),说明abc是一个函数(这是abc真面目)。那么函数的返回值是什么类型的呢?abcint a)接着和*(右边的*)结合,即*abcint a),说明函数abc的返回值是指针类型的?那是什么类型的指针呢?int  *(*abcint a)可以看出,abcint a)的返回值是指向int型指针的指针。

4.      指向函数返回值为int的函数指针。由(*abc)可以看出,*先与abc结合,所以abc是一个指针(而不是函数),该指针指向形参为int a,返回值为int的函数。

5.      指向“int 型数组”的指针。从(*abc)可以看出,abc是一个指针,那是什么类型的指针呢?(*abc)和后面的[]结合,即(*abc[6],所以abc指向一个数组,那么数组元素的类型呢?从int *abc[6]可以看出,数组元素的类型为int型。再分析一遍,指针abc指向一个数组,数组的元素类型为int型,即abc是一个指向int型数组的指针。

6.      返回值为“int型指针”的函数。由于()的优先级高于*,所以abc首先和()结合,即abc(int a),由此看出abc是一个函数(而不是指针),那么该函数的返回值是什么类型的呢?abcint a)和前面的*结合,即*abcint a),可以看出,函数abc的返回值是指针类型的。接着,*abcint a)和int结合,即int *abcint a)。再分析一遍,abc是一个函数,返回值为int型指针。

7.      元素为指向“返回值为int型指针的指针的函数”的指针数组。由于[]的优先级高于*,所以abc先和[]结合,即abc[6],所以abc是一个数组。然后abc[6]*结合,即*abc[6],说明数组abc的每个元素是指针,且该指针指向形参为int a,返回值为int指针的指针的函数。

8.      int型指针的指针数组。[]的优先级高于*,所以abc首先和[]结合,即abc[],所以abc是一个数组,然后abc[6]*(右边的*)结合,即*abc[6],可以看出数组abc的每个元素为指针。那么该指针指向什么呢?接着,*abc[6]和左边的*结合(*的结合顺序为从右到左),即**abc[6]),所以数组abc的每个元素为指针,且该指针指向int型的指针,也就是说,数组abc的每个元素为int型的指针的指针。

9.      指向“int型指针数组”的指针。由于()的优先级高于[],所以abc*先结合,即*abc,所以abc是一个指针(这是本质)。而下标[]的优先级高于*,所以*abc然后和[]结合,即(*abc[6],可以看出,abc指向的是一个数组,数组的元素类型为int *,即int型指针。

10.  返回值为“指向返回值为int型指针的函数指针”的函数。是不是有些头晕呢?没关系,不管你头晕不晕,我都会让你清醒的。由于()的优先级高于*,所以abc先和()结合,即abcint a),说明abc是个函数,这是本质。然后abcint a)和前面的*结合,即*abcint a),说明函数的返回值为指针,那么该指针(ptr1)指向什么呢?int **abc(int a))(int a),看到红色的部分了吗?可以看出,ptr1指向一个函数,该函数形参为int a,返回值为int型指针。最后我们再分析一遍,abcint a)函数的返回值是一个指针,该指针指向形参为int a,返回值为int型指针的函数。

11.  指向返回值为“指向返回值为int的函数指针”的函数指针。从(*abc(int a)可以看出,abc是一个函数指针,那么该函数指针所指的函数(f)返回值是什么类型的呢?从**abc(int a)可以看出,函数f的返回值为指针类型(ptr_type),那ptr_type到底是什么类型的呢(指向intchar,还是函数)?从int  (**abc(int a))(int a)可以看出,ptr_type是函数指针,所指向的函数形参为(int a),返回值为int型。

12.  指向函数返回值为“返回值为int的函数指针的指针”的函数指针。分析参考11

13.  指向函数返回值为“指向int型数组的指针”的函数指针。abc先和*结合,即*abcabc是一个指针。接着,*abc和()结合,即(*abc)(int a),abc指向的是一个函数,即abc是一个函数指针。那么abc指向的函数返回值是什么类型呢?(*abc)(int a)接着和前面的*结合,即**abc(int a),说明abc所指向的函数的返回值是一个指针,那么这个指针(ptr)指向哪儿呢?接着往下看,(**abc(int a))[6]ptr指向一个数组,数组的元素类型为int型。再分析一遍,函数指针abc所指的函数返回值是一个指针,该指针指向int型的数组。

14.  指向函数返回值为“指向‘返回值为int型指针的函数指针’的数组的指针”的函数指针。看到这个表达式,你是不是头有点大了?如果你的answeryes,那么恭喜你,说明你还是个正常的地球人。哈哈!开个玩笑。从(*abc(int a)可以看出,abc是一个函数指针,即指针abc指向的是一个函数(f)。那么函数f的返回值是什么类型的呢?从**abc(int a)可以看出,函数f的返回值类型是指针型(ptr)的,那么这个指针指向哪里呢?从(**abc(int a)[6]可以看出,ptr指向一个数组,那么该数组(arr)的元素是什么类型的呢?从***abc(int a)[6]arr的数组的元素类型为指针类型(ptr_type),那是什么类型的是指针呢(指向intchar,还是函数)?从int *(***abc(int a)[6])(int a)可以看出,ptr_type是指向函数的指针,该函数的形参为int a,返回值为int型指针。

 

如果我们碰到复杂的类型声明,该如何解析它?例如:

char (*a[3])(int);

a 到底被声明为什么东东?指针?数组?还是函数?

分析时,从 a 最接近(按运算符优先级)处开始。我们看到 a 最接近符号是 [ ] —— 注意 * [ ] 的优先级低。 a 后既然有 [ ] ,那么 a 是数组,而且是包含 3 个元素的数组。

那这个数组的每个元素是什么类型呢?虽然数组 a 只含有 a[0] a[1] a[2] 三个元素 a[3] 实际上已经越界 但在分析数组 a 的元素的类型时 我们正好需要形式上的元素 a[3] 知道 a[3] 的类型 就知道了 a 的元素的类型 a[3] 是什么类型?是指针 因为它的前面有 *. 由此可知,数组 a 的元素是指针。

光说是指针还不够。对于指针,必须说出它指向的东东是什么类型。它指向的东东是什么 ,就看 *a[3] 是什么 a[3] 是指针 它指向的东东当然是 *a[3] 继续按优先级观察 我们看到 *a[3] 后面有小括号,所以可以肯定 *a[3] 是函数。即数组 a 的元素是指向函数的指针。指向的是什么类型的函数?这很明显,是入参为 int 、返回值为 char 的类型的函数。至此解析完毕。

 

按上述方法,再复杂的也可以一步步解析出来。

就像习武不是为了打人而是为了防身一样,我们了解上述方法是为了看懂别人写的复杂声明 ,而不是为了在实践中自己去构造这种复杂的东东。实在需要复杂声明时,可以用 typede f替代一部分。例如上面语句可改成两句:

typedef char (*FUN_PTR)(int);

FUN_PTR a[3];

这样就清晰多了。

此外 上面的分析方法还让我们对某些东西的本质更加清楚 比如 n 维数组的本质都是一维数组。看个具体的例子:

int a[3][5];

这句声明的是一个包 3 个元素的一维数组 其每个元素又是一个 5 in t 数构成的数组

我们不能理解为: a 是一个包含 5 个元素的一维数组,其每个元素又是一个由 3 int 数构成的数组。为什么?还是按上面的方法分析,这里从略。

有的书上或网上提供 " 向右看 , 向左看 " 的方法 , 其实缺乏通用性 , 比如它不适用于对多维数组本质的分析 . 而且这种方法掩盖了本质 . 本质应该是按上面所讲的 , 根据运算符优先级逐层剥开。

 

关于上面那个typedef的定义为什么和上面那个例子等价的问题,另启一篇讲述。

 

阅读(1835) | 评论(0) | 转发(1) |
0

上一篇:二叉树的遍历

下一篇:typedef的用法

给主人留下些什么吧!~~