主函数可以在C ++中调用自身吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主函数可以在C ++中调用自身吗?相关的知识,希望对你有一定的参考价值。
任何人都可以告诉下面的代码有什么问题吗?
int main () {
return main();
}
我测试过,它编译正确。它一直在运行。现场背后的诀窍呢?
TLDR:调用main
会导致未定义的行为。
关于标准中使用的术语以及对程序员和编译器的含义似乎存在混淆。
首先,标准单独决定了C ++语言的一切。如果特定编译器的特定版本允许某些特定操作,则与该操作是否合法无关。对于帖子的其余部分,我指的是ISO03标准。
所以再次引用,标准在§3.6.1.3中说:
函数main不得在程序中使用。
另外,§3.2将“used”定义为:
如果对象或非重载函数的名称出现在可能已评估的表达式中,则使用该函数。
这意味着一旦程序开始执行,就不应再次输入main
。这意味着程序员不能调用main
,这意味着编译器不能插入另一个调用main
(为什么会这样,谁知道),你不能接受main的地址并调用它等等。你甚至无法调用main
。
对main
的唯一调用应该是程序运行的运行时库;所有其他调用都会调用未定义的行为。 (这意味着什么都可能发生!)
现在进入编译器行为:
可诊断规则定义为(§1.4.1):
可诊断规则集包含本国际标准中的所有语法规则和语义规则,但那些包含“无需诊断”的明确表示法或被描述为导致“未定义行为”的规则除外。
在我们的例子中,§3.6.1.3定义了可诊断的规则。以下是编译器应根据§1.4.2进行的操作:
- 如果某个程序不违反本国际标准中的规则,则符合要求的实施应在其资源限制内接受并正确执行该程序。 - 如果程序包含违反任何可诊断规则的行为,则符合要求的实现应至少发出一条诊断消息,但该行为除外 - 如果某个程序包含违反不需要诊断的规则,则本国际标准不对该程序的实施提出任何要求。
因此编译器不需要执行规则。所有编译器必须做的是采用格式良好的程序(§1.3.14)并将它们转换为可执行程序。编译器可以自由地发出警告,错误等等,只要它不与语言冲突。根据第二个条款,在特定情况下需要显示消息。
对于这个特殊问题,在gcc上,-pedantic
选项会警告在程序中调用main
的非法性。 Visual Studio不会警告调用main
,但在任何警告级别(大于0)它将警告该程序的递归性质。
对于你应该期待的答案,这一切意味着什么?这意味着尝试确定代码片段发布的内容是完全没有意义的。调用main
会导致未定义的行为,并且尝试定义未定义的行为显然是一个失败的原因。唯一诚实的回答,任何人都可以给“当我打电话给main
会发生什么?”是“任何东西”。
我希望这可以解决问题。
在C ++中调用main
是非法的(§3.6.1.3):
函数main不得在程序中使用。
您的编译器允许非法行为。
它永远循环,因为,好吧,main
称main
,谁叫main
,谁叫main
,等等。
这就像是一个贩毒者。非常非法,但编译甚至可以在一段时间内完成...
当然如果你真的想要递归调用你的main函数,有时候有很好的理由,你应该这样做
int mymain()
{
return mymain();
}
int main()
{
return mymain();
}
问题是,你为什么要这样做?
main应该是您程序的单个入口点。再次调用它本质上会重新启动您的程序,但没有新的流程实例;没有新堆栈,没有新堆等
如果你真的需要递归,递归调用一个单独的函数。
C ++标准,在3.6.1节中说:
函数main不得在程序中使用(3.2)。
它指定,你不应该在你的程序中调用它。
当你编写递归代码时,你需要确保在某些时候你停止递归,否则你只是写了一个无限循环。
你有哪些。
你应该期望这段代码会消失很长时间,然后最终因堆栈溢出而崩溃。
你有两个问题。第一个是调用main,正如已经指出的那样,它们都违反了标准的标准和意图。
更大的问题是你写了一个没有任何关闭点的递归调用。你的问题似乎假设初始版本调用的main版本将返回。但是,大多数语言(事实上我只能想到)允许无限递归:如果函数调用自身,那么该版本也将如此。唯一的限制是系统资源。
因此,您需要在条件中包装调用,并在需要时继续调用。在您的示例中,将全局整数集添加到要递归的级别数将起作用。像这样的东西:
`
int levels = 3;
int main() {
if(levels) {
cout << "Recursing another level...
";
levels--;
main();
}
else {
cout << "Reached the bottom.
";
}
return levels;
}
`
将退出。
虽然你的程序显然没有任何意义,因为它永远循环,所以看起来可能是这样的:
int main( int argc, char* argv[] )
{
if( argc )
{
// do something with argv[0]
main( argc - 1, &argv[1] );
}
else
{
// rest of application having loaded your arguments
}
}
但是标准不允许这样做。 (见其他答案)
当然,你可以通过这样做来实现
int myFunc( int argc, char * argv[] )
{
// I can recurse this if I like and just get main to forward straight to here
}
以上是关于主函数可以在C ++中调用自身吗?的主要内容,如果未能解决你的问题,请参考以下文章