在 C 中的函数内部声明函数
Declaring function inside function in C
我在一次在线考试中发现了这个问题。这是代码:
#include <stdio.h>
int main(void) {
int demo();
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
考完才看到答案。这是答案:
MorningMorning
我看了解释,但不明白为什么是这个答案。
我的意思是,int demo();
行不应该导致任何 "problem"?
任何解释都是有帮助的。谢谢
这不是问题,因为 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 main(void) { int demo(); /*...*/ }; int demo(){ /*...*/ }
相当于
int main(void) { extern int demo(); /*...*/ }; int 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之后,demo
是一个函数指示符(它与函数指针不同,不像数组指示符与指针不同)数组的第一个元素)。但是,与数组一样,函数指示符几乎总是衰减为函数指针(请参阅 6.3.2.1p4),并且这种类型的衰减也发生在函数调用中。本质上 demo();
衰减 demo
到一个指针然后调用
函数指针。将 *
应用于这样的指针再次产生函数指示符,该指示符再次衰减为指针以进行调用。
诚然,所有这些东西都非常奇怪和深奥,我什至想不出区分有用的情况。恕我直言,最好坚持 demo();
或 (demo)()
(如果你想抑制宏扩展)并且永远不要使用 (*demo)()
(至少不是在函数上 - 在它所在的函数指针上至少有点信息),尤其是 (&demo)()
因为它除了混淆 reader.
外没有什么用处
其他答案没有解释
(*demo)();
部分。以下是部分解释:
demo
(没有括号)是函数pointer。所以你可以先取消引用它以获得一个函数 然后 用括号调用它(将取消引用的对象包装到括号中否则这意味着你想取消引用 return 函数的值)
所以它严格等同于
demo();
(当函数指针存储在变量中时,该表示法很有用,这里它只是比必要的更隐晦)
我在一次在线考试中发现了这个问题。这是代码:
#include <stdio.h>
int main(void) {
int demo();
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
考完才看到答案。这是答案:
MorningMorning
我看了解释,但不明白为什么是这个答案。
我的意思是,int demo();
行不应该导致任何 "problem"?
任何解释都是有帮助的。谢谢
这不是问题,因为 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 main(void) { int demo(); /*...*/ }; int demo(){ /*...*/ }
相当于
int main(void) { extern int demo(); /*...*/ }; int 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之后,demo
是一个函数指示符(它与函数指针不同,不像数组指示符与指针不同)数组的第一个元素)。但是,与数组一样,函数指示符几乎总是衰减为函数指针(请参阅 6.3.2.1p4),并且这种类型的衰减也发生在函数调用中。本质上 demo();
衰减 demo
到一个指针然后调用
函数指针。将 *
应用于这样的指针再次产生函数指示符,该指示符再次衰减为指针以进行调用。
诚然,所有这些东西都非常奇怪和深奥,我什至想不出区分有用的情况。恕我直言,最好坚持 demo();
或 (demo)()
(如果你想抑制宏扩展)并且永远不要使用 (*demo)()
(至少不是在函数上 - 在它所在的函数指针上至少有点信息),尤其是 (&demo)()
因为它除了混淆 reader.
其他答案没有解释
(*demo)();
部分。以下是部分解释:
demo
(没有括号)是函数pointer。所以你可以先取消引用它以获得一个函数 然后 用括号调用它(将取消引用的对象包装到括号中否则这意味着你想取消引用 return 函数的值)
所以它严格等同于
demo();
(当函数指针存储在变量中时,该表示法很有用,这里它只是比必要的更隐晦)