#include <stdio.h>
int main(void) {
int demo();
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
我在考试后看到了答案。这是答案:
MorningMorning
我看了解释,但不明白为什么这是答案。我的意思是,int demo();
这一行难道不会引起"问题"吗?
希望能有解释。谢谢。
#include <stdio.h>
int main(void) {
int demo();
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
MorningMorning
我看了解释,但不明白为什么这是答案。我的意思是,int demo();
这一行难道不会引起"问题"吗?
希望能有解释。谢谢。
这并不是问题,因为int demo();
不是函数定义,而只是外部声明,说明(声明)了存在这样一个函数。
在C语言中,你不能定义嵌套函数:
int main(void) {
int demo() {} //Error: nested function!!!
}
但是你可以很好地声明一个函数。实际上,这相当于:
#include <stdio.h>
int demo(); //function declaration, not definition
int main(void) {
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
demo()
只在 main
内部可见之外,其他都一样。int demo();
这行代码,但它仍然可以正常工作。 - Debanik Dawnint
。也许在20世纪70年代很方便,但非常危险。打开你的编译器警告,你就会看到这种危险(并保持它们开启!)。 - rodrigo(*demo)();
部分。以下是部分解释:
demo
(不带括号)是函数指针。因此,您可以首先对其进行解引用以获取一个函数,然后使用括号调用它(将解引用的对象包装到括号中,否则它意味着您要解引用函数的返回值)
因此,它严格等同于
demo();
demo()
和(*demo)()
相同,那么这是否意味着demo
和*demo
是完全相同的东西?这怎么可能呢? - Debanik Dawnhello()
的函数,然后在主函数中打印了hello
、*hello
和&hello
的值。它们完全相同,我不明白。 - Debanik Dawnhello
是例程的地址。它不像普通变量。获取地址的地址或取消引用它都没有影响。 - Jean-François Fabreint main(void) { int demo(); /*...*/ }; int demo(){ /*...*/ }
等价于
int main(void) { extern int demo(); /*...*/ }; int demo(){ /*...*/ }
它在main函数内部声明了具有外部链接的demo函数。
demo
标识符将在作用域结束之前有效,但demo
将是一个普通的外部函数。
不幸的是,对于static
函数,您无法这样做,因为标准(http://port70.net/~nsz/c/c11/n1570.html#note30)使得像
int main(void) { static int demo(); } static int demo(){ /*...*/ }
非法。
至于为什么(*demo)();
可以工作并且在这种情况下等效于demo();
或(&demo)();
或(*&demo)();
:
int demo();
的方法后,demo
是一个函数指示器(它与函数指针不同,就像数组指示器与指向数组第一个元素的指针不同一样)。与数组类似,函数指示器几乎总是衰变为函数指针(参见 6.3.2.1p4),这种衰变类型也发生在函数调用中。实际上,demo();
将 demo
转化为指针并且调用函数指针。对这样的指针应用 *
再次产生函数指示器,然后再次衰变为指向调用的指针。
不可否认,所有这些东西都非常奇怪和深奥,我甚至想不到有什么情况下区别是有用的。在我看来,最好坚持使用demo();
或(demo)()
(如果您想抑制宏扩展),永远不要使用(*demo)()
(至少不要在函数上使用--在函数指针上使用还有一定的信息量),尤其不要使用(&demo)()
,因为它除了让读者困惑之外没有任何作用。
(*demo)();
的部分。 - Jean-François Fabre