我该如何理解这个C类型声明?

5
double (*bar(int, double(*)(double,double[])))(double);

在查看讲义幻灯片时,我发现留给学生的练习:

用简单易懂的语言说明这个C声明中bar的类型是什么?

帮忙给我讲解一下。除了最后会返回一个double之外,我甚至不知道从哪里开始。


1
不知道这是什么类型,但突然间我想起了 Tim Hortons... - Marc B
1
声明bar为函数(int,指向函数(double,返回double的double数组)的指针)返回指向函数(double)返回double的指针。 (我作弊了。) - Hot Licks
3
第一反应应该是抓住编码如此之糟的可怜家伙,用简明易懂的英语对他大喊大叫 :) - Sergey Kalinichenko
这个问题是为什么应该自由使用typedef。 - bobroxsox
1
我不确定为什么这个问题被关闭为“过于本地化”。虽然大多数人不需要理解代码的确切行,但理解复杂的C声明的能力是非常有用的技能...这个问题只是一个很好的例子。 - Mike
显示剩余3条评论
2个回答

10

如果您不确定,您可以始终使用 K&R 中描述的 cdecl 实用程序:

$ cdecl
Type `help' or `?' for help
cdecl> explain double (*bar(int, double(*)(double,double[])))(double);
declare bar as function 
(int, pointer to function (double, array of double) returning double)
returning pointer to function (double) returning double

所以,bar是一个函数,它接受一个int和一个指向一个函数的指针,该函数接受一个doubledouble[],并返回一个double

double(*)(double,double[]))

并且bar返回一个指针,它指向另一个接受一个double并返回一个double的函数。

double(*)(double)

如果你所说的“那个”是指幻灯片上的声明,我猜它是为了让学生接受残酷和不寻常的惩罚而存在的;-) - Sergey Kalinichenko
4
只是我自己感觉还是原始代码更易读,相比于 cdecl 的特定输出?:-P - Nikos C.
@NikosC。不,cdecl的输出并不更容易阅读/理解,因为它只是另一种类型的纯文本代码,而不是人类大脑本地的AST。 - user529758
1
@NikosC。在腐烂的苹果中选择很少 :) - Sergey Kalinichenko
1
@Aerovistae 选择对你最有帮助的答案。这就是勾选标记的意义所在。只有当你选择了一个被踩的答案(也许即使它只有-1分),你才需要停下来思考是否真的应该接受那个答案。 - Daniel Fischer
显示剩余3条评论

7

本答案由使用螺旋规则的能力带给您。通过从未知元素开始阅读并在其周围阅读(首先解决括号内的内容),能够理解复杂表达式是一项非常有用的技能,特别是在阅读代码时。

        bar                                            - bar
        bar()                                          - is a function
        bar(int, )                                     - which takes an int...
        bar(int, (*)())                                - and a function pointer
        bar(int, double(*)())                          - which returns a double
        bar(int, double(*)(double, ))                  - and takes a double...
        bar(int, double(*)(double, double[]))          - and an array of doubles
      (*bar(int, double(*)(double, double[])))         - and returns a pointer
      (*bar(int, double(*)(double, double[])))()       - to a function
      (*bar(int, double(*)(double, double[])))(double) - taking a double
double(*bar(int, double(*)(double, double[])))(double) - which returns a double

那是一种比较麻烦的方法...当然也有一些网站可以更简单地完成这个过程,例如cdecl网站;但即使没有网络连接,能够阅读代码也是很重要的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接