这是有效的标准C吗?

7
我正在审查一些优化库,并遇到了以下函数签名:
double solvopt(unsigned short n,
           double x[], 
           double fun(), 
           void grad(),
           double options[],
           double func(),
           void gradc()
          )

请注意,fun()和gard()被传递为函数。我的问题是这是否是有效的标准C语法。
谢谢。
3个回答

7
使用double fun()而不是double (*fun)()是一种过时的形式,它只在标准C中有效,而在C++中从未有效过,并且如果我没记错的话,仅在声明函数参数时有效。(就像ary[]一样,在函数参数中是合法的,但在未初始化的变量中是非法的)
由于(在C中)不可能将函数按值传递给另一个函数,编译器只是将double fun()解释为返回double类型的函数的指针。
因此,这是有效的(但已经过时并不再流行)。

6
关于C++的说法不正确。在标准的C和标准的C++中,这种形式是完全有效的。这种方式没有任何陈旧的内容。在参数声明中,函数类型会像数组类型一样逐渐被解析为指针类型。在C和C++中,它们的工作方式完全相同(除了“()”参数列表的含义,在本例中无关紧要)。 - AnT stands with Russia
@AndreyT:奇怪的是你从来没有看到过这种形式的使用,但我会修改答案。 - John Knoeller
当使用初始化列表时,array[]作为变量是合法的。例如:int array[] = {2, 3, 5, 7, 11, 13}; - wallyk
1
它在C99标准(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)的第6.7.5.3节“函数声明符(包括原型)”中。 限制条件8。 - ziya
@wallyk:array[] 在 C 和 C++ 中的任何非定义声明中都是合法的。唯一的区别是无大小的数组类型是不完整的 - AnT stands with Russia

2

func()gradc()是具有未知参数的函数的正确形式。我相信即使在1975年左右的Unix 6中,这也是一种可接受的语法。

[]参数与过去相同,现在也是如此。事实上,我记得在1980年代有一场争论,争论的焦点是哪种方式更为合适:

int main (int argc, char **argv, char **envp)

或者

int main (int argc, char *argv[], char *envp[])

效果没有差异。争议在于哪种语义更正确。


1
我总是更喜欢不在函数参数中使用[]*argv []**argv更加视觉上令人困惑,如果您使用括号,新的C程序员可能会认为该变量实际上是一个数组,而不是指针,并尝试对其进行一些邪恶的sizeof(x)/ sizeof(x [0])类型的操作。最好(在我看来)明确它不是数组,也不应该被视为数组。 - Chris Lutz
2
我一直是少数派,支持使用 **argv。很高兴找到另一个同道中人。 - wallyk

1

你的数组参数(x 和 options)应该是指针。

当你使用括号引用一个函数,比如“func()”或者“gradc()”,这会调用该函数。但是仅使用函数名本身就是一个可被解引用来调用相应函数的代码指针。

如果不确定,请尝试使用 ANSI C 编译器编译此代码 - 很多编译器都提供了一个 ANSI 兼容性开关以强制执行标准兼容性。另外,K&R 书 是你的朋友。

这是一个作业问题吗?


它们可以被看成是同样的,但在这个声明中 double x[]double *x 是等效的。 - Chris Lutz
不,先生,那不是一道家庭作业问题。我甚至不是C程序员,但被要求审查一些C代码。 - leon

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