主函数可以在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不得在程序中使用。

您的编译器允许非法行为。

它永远循环,因为,好吧,mainmain,谁叫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 ++中调用自身吗?的主要内容,如果未能解决你的问题,请参考以下文章

函数可以调用它本身吗?

C# 主窗口调用子窗口的值传递?

Cgo 可以调用在另一个目录中声明的 C 函数吗?

我可以从c ++调用用cupy代码编写的cuda代码吗?

jquery 调用子窗口函数

c语言中如何一个函数的多次调用