【问题标题】:Call main() itself in c++?在 C++ 中调用 main() 本身?
【发布时间】:2010-03-28 12:44:28
【问题描述】:
#include <iostream>
#include <cstdlib>

int main() {
    cout << "!!!Hello World!!!" << endl;
    system("pause");
    return main();
}

上述方法有效,但它硬编码了main() 函数。有没有神奇的变量或宏来获取当前运行的函数?

【问题讨论】:

  • 如果你想得到一个函数指针或指向当前函数的东西,我认为这是不可能的。
  • @Michael 其实假设 main() 是一个可以调用的函数,那么上面的尾递归可以被编译器优化成一个循环,这样就可以“工作”了。
  • @Neil:你能说出一个优化尾调用的 C 或 C++ 编译器吗?
  • @ttmrichter 在这种特定情况下不,因为调用是非法的,但在一般情况下,GCC 会这样做。见stackoverflow.com/questions/2385599/…

标签: c++


【解决方案1】:

在“C++”中是否允许?没有。

在实践中,你能打电话给main()吗?是的。

无论 C++ 标准怎么说,这都不会阻止 Linux g++ 编译器在 main() 中使用 main() 编译代码。

#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
 int y = rand() % 10; // returns 3, then 6, then 7
 cout << "y = " << y << endl;
 return (y == 7) ? 0 : main();
}

我们可以这样做:

 > g++ g.cpp; ./a.out
 y = 3
 y = 6
 y = 7

查看程序集,我们看到 main 的调用方式与其他任何函数一样:

main:
        ...
        cmpl    $7, -12(%rbp)
        je      .L7
        call    main
        ...
.L7:
        ...
        leave
        ret

并不是说这种行为是有保证的,但看起来 g++ 似乎并不真正关心标准,除了这个带有-pedantic 的讽刺警告

g.cpp:8: error: ISO C++ forbids taking address of function '::main'

【讨论】:

    【解决方案2】:

    如果特定的实现允许这样做,则它的行为不正确(a)C++14, 3.6.1 Main function /3 中非常明确的标准状态:

    函数main不得在程序中使用。


    (a) 请记住,许多实现松散地遵循标准的某些部分,更喜欢权力而不是严格。这可能会带来不幸的副作用,即您的代码可能无法移植到其他编译器,甚至是 same 编译器的其他版本。

    许多实现也将允许您采取更严格的观点,例如使用g++ -std=c++11 -Werror=pedantic 捕获在这个问题中购买的特定问题,以及相当多的其他问题。根据1.4 Implementation compliance,正是这种翻译“模式”允许实现声称符合标准:

    如果程序包含对任何可诊断规则的违反...,则符合要求的实现应发出至少一条诊断消息。

    您会发现在这种情况下允许代码编译和运行仍然很有可能,因为“诊断消息”可能意味着警告而不是错误。

    【讨论】:

      【解决方案3】:

      C++ 标准规定您不能从自己的代码中调用 main()。至于获取当前函数的名称,你可以使用__FUNCTION__ 宏,但这又不是标准的:

      #include <iostream>
      using namespace std;
      
      void foo() {
         cout << __FUNCTION__ << endl;
      }
      
      int main() {
         foo();
      }
      

      如果支持__FUNCTION__,应该打印“foo”或类似的东西。

      【讨论】:

      • @Neil,__FUNCTION__ 将是字符串...无法调用。
      • @Michael 我知道。我不清楚(不是第一次)@Mask 实际上在问什么。就函数元数据而言,以上内容与您将获得的一样好。
      • 好吧,如果你要假设非标准__FUNCTION__,那么你也可以假设非标准dlopendlsym(或等效),并获得一个函数指针方式...
      【解决方案4】:

      一般来说,不会。现在你知道编译器需要知道你在编译时调用的确切函数就足够了。比方说,你不能做魔术,比方说

      func = "my_function"; 
      func(); 
      

      如果被调用的函数名在运行时会改变。 (有一些例外和方法,但你不需要那个)。

      不要将其视为硬编码:事实并非如此。如果你需要调用这个函数,那么你只需要写它的名字,不要试图抽象它什么的。

      另外,现在是学习 while 循环、无限循环和完全不用函数调用编写代码的好方法,例如

      int main()
      {
          while (1) {
              cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
              system("pause");
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        • 2012-01-10
        • 2017-04-22
        • 1970-01-01
        • 1970-01-01
        • 2012-02-27
        • 1970-01-01
        相关资源
        最近更新 更多