【问题标题】:how to start the execution of a program in c/c++ from a different function,but not main() [duplicate]如何从不同的函数开始执行 c/c++ 中的程序,但不是 main() [重复]
【发布时间】:2012-11-03 01:48:24
【问题描述】:

可能重复:
Does the program execution always start from main in C?

我想开始执行我的程序,它包含 2 个函数(不包括 main)

void check(void)
void execute(void)

我想从 check() 开始执行,在 c/c++ 中可以吗?

【问题讨论】:

  • 这个问题被问了很多,these hits 上的任何一个回答你的问题吗?
  • 您可以编写自己的引导代码来调用check() 而不是main()。或者你可以写main(),所以它调用check()。后者更容易做到几个数量级。 C 标准说(ISO/IEC 9899:2011 §5.12.2.1 程序启动)程序启动时调用的函数名为main
  • 这个问题的答案取决于您使用的编译器。你的操作系统和编译器是什么?
  • 你可以制作一个独立的节目,所有的赌注都没有。

标签: c++ c function main


【解决方案1】:

你可以用一个简单的包装器来做到这一点:

int main()
{
    check();
}

由于标准明确指定 main 作为程序入口点,因此您无法以任何其他方式进行移植。

编辑评论:永远不要这样做。在 C++ 中,您可以滥用静态初始化在静态初始化期间在 main 之前调用 check,但您仍然不能从 check 合法地调用 main。你可以让check 先运行。正如评论中所指出的,这在 C 中不起作用,因为它需要常量初始化器。

// At file scope.
bool abuse_the_language = (check(), true);

int main()
{
    // No op if desired.
}

【讨论】:

  • 我不必首先调用 main()。必须调用 check,然后 main.任何想法?
  • 为你获得支持而感到羞耻(但无论如何+1)。
  • 我不认为这是合法的 C。具有静态生命周期的对象的初始化程序应该是常量。我所有的编译器都拒绝这个代码。
【解决方案2】:

编译器可能支持它。比如gcc,可以使用-nostartfiles和--entry=xxx来设置程序的入口点。默认入口点是_start,它将调用函数main。

【讨论】:

    【解决方案3】:

    我找到了解决我自己问题的方法。 我们可以简单地使用

    #pragma startup function-name <priority>
    #pragma exit function-name <priority>
    

    这两个 pragma 允许程序指定应在程序启动时(在调用 main 函数之前)或程序退出(就在程序通过 _exit 终止之前)调用的函数。

    指定的函数名必须是先前声明的不带参数并返回 void 的函数;换句话说,它应该被声明为:

    void func(void);
    

    可选的优先级参数应该是64到255范围内的整数。最高优先级为0。具有较高优先级的函数在启动时首先被调用,在退出时最后被调用。如果不指定优先级,则默认为 100。 谢谢!

    【讨论】:

    • 请记住,您的代码不能以这种方式移植。例如 GCC 不支持 #pragma startup 并且会抛出警告
    • 我上面已经提到我使用的是turbo c/c++。谢谢。
    【解决方案4】:

    有一种人为的方法可以实现这一点,但这只不过是一种 hack。

    这个想法是创建一个包含主函数的静态库,并让它调用你的“检查”函数。 链接器将在链接到您的“程序”时解析符号,并且您的“程序”代码本身确实没有 main。

    不建议这样做,除非您有非常特殊的需求(想到的一个例子是 Windows 屏幕保护程序,因为 Windows SDK 附带的帮助程序库具有执行特定初始化的主要功能,例如解析命令行)。

    【讨论】:

      【解决方案5】:

      各种链接器有不同的选项来指定入口点。例如。微软链接器使用/ENTRY:function

      /ENTRY 选项指定一个入口点函数作为开始 .exe 文件或 DLL 的地址。

      GNU 的 ld uses the -e or ENTRY() in the command file.

      需要说,修改入口点是一项非常高级的功能,您必须绝对了解它的工作原理。一方面,它可能会导致跳过加载标准库初始化。

      【讨论】:

      • 我找到了解决我自己问题的方法。我们可以简单地使用
      【解决方案6】:

      您可以通过在 main 启动之前创建一个对象来“拦截”对 main 的调用。构造函数需要执行你的函数。

      #include <iostream>
      
      void foo()
      {
        // do stuff
      
        std::cout<<"exiting from foo" <<std::endl;
      }
      
      struct A
      {
        A(){ foo(); };
      };
      
      static A a;
      
      int main()
      {
        // something
        std::cout<<"starting main()" <<std::endl;
      }
      

      【讨论】:

      • 这里的风险是其他应该初始化的对象没有被初始化。
      • -1:除非您牢记静态初始化的规则……但即使在这种情况下,我也不会通过由于静态初始化而启动的事件来限制任何应用程序的运行。这是完全不受控制的流程。
      【解决方案7】:

      你不能从 main 以外的东西开始,尽管有一些方法可以让 一些代码在 main 之前执行。

      将代码放在静态初始化块中将使代码在 main 之前运行;但是,它不会是 100% 可控的。虽然您可以确保它在 main 之前运行,但您不能指定两个静态初始化块在它们都在 main 之前执行之前运行的顺序。

      链接器和加载器都有 main 的概念,作为 C / C++ 程序的共享“理解”开始;但是,有一些代码在 main 之前运行。此代码负责程序的“设置环境”(例如设置stdincin)。通过将代码放在静态初始化块中,您实际上是在说,“嘿,您也需要这样做才能拥有正确的环境”。一般来说,这应该是一个小东西,可以独立于其他项目的执行顺序。

      如果你需要在main之前按顺序执行两三件事,那就把它们做成合适的函数,在main开头调用。

      【讨论】:

        【解决方案8】:

        main 调用check 似乎是最合乎逻辑的解决方案,但您仍然可以探索使用/ENTRY 为您的应用程序定义另一个入口点。请参阅here 了解更多信息。

        【讨论】:

          【解决方案9】:
          int main()
          {
              check();
              return 0;
          }
          

          【讨论】:

          • 顺便说一句,return 0; 是隐含的......
          • 在我看来,返回值的函数最后应该有一个return value; 语句。我更喜欢如图所示编写的代码。
          • 我认为很多人都同意 Jonathan 8^)
          猜你喜欢
          • 1970-01-01
          • 2019-02-20
          • 1970-01-01
          • 1970-01-01
          • 2021-07-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          相关资源
          最近更新 更多