main()是否在C++中重载?

iam*_*ind 67 c++ program-entry-point overloading

main()存在2个有效版本C++:

int main()  // version 1
int main(int argc, char **argv)  // version 2
Run Code Online (Sandbox Code Playgroud)

但两种重载都不能同时共存.为什么不?(潜在用例:从终端运行程序时,如果没有传递参数,则调用第一个版本,否则第二个版本被调用.)

编译器是否执行特殊检查以允许每个二进制文件只有一个版本?

Naw*_*waz 65

§3.6.1/ 2(C++ 03)说

实现不应预定义该main功能.此功能不应过载.它应该具有int类型的返回类型,否则其类型是实现定义的.所有实现都应允许以下两个主要定义:

   int main() { /* ... */ }
   int main(int argc, char* argv[]) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

你可以使用它们中的任何一个.两者都符合标准.

而且,因为char *argv[]相当于char **argv,取而代之char *argv[]char **argv是没有任何区别.


但这两个版本不能同时共存!(用例可以是:从命令提示符运行二进制文件时,如果不传递参数,则应调用第一个版本,否则调用第二个版本).

不可以.两个版本不能同时共存.一个程序可以只有一个main功能.哪一个,取决于您的选择.如果要处理命令行参数,那么您必须选择第二个版本,否则第一个版本就足够了.另请注意,如果您使用第二个版本,并且不传递任何命令行参数,那么它就没有任何损害.它不会导致任何错误.您只需要解释argcargv相应地根据它们的价值,编写程序的逻辑和流程.

  • @Tony:鉴于问题实际上是询问*overload*s而C不支持重载,我只能假设C标签被滥用了.好吧,那个以及标题和第一行确实明确表达了对C++的讨论这一事实. (17认同)
  • 鉴于该问题被标记为2种语言,目前尚不清楚您引用的是哪种标准.... (5认同)
  • @Tony:我现在提到了.此外,`这个函数不应该重载'明确它的C++.毕竟,C不支持**任何**函数的*重载*. (5认同)
  • @Tony,`main`实际上不是程序的入口点,它是第一个被调用的函数(*main*),但是在调用*`main`之前必须进行静态初始化.我怀疑DOS/Windows有不同的应用程序入口点(可能是有不同的可执行格式),我也怀疑在`wmain`,`_ tmain`和`WinMain`的情况下程序不包含一个简单的`main`函数(在库中定义并链接在一起)转发调用...但是我必须有一个windows环境来实际测试它,所以我不会断言它是真的 (2认同)
  • David 关于 Windows 入口点如何工作的猜测是完全正确的。库代码中隐藏着一个普通的“main”函数。您看到的“_tWinMain”内容不是官方入口点,它只是*您的*代码所关注的入口点。 (2认同)

Ski*_*izz 20

Windows和Unix有:

int main(int argc, char **argv, char **envp)
Run Code Online (Sandbox Code Playgroud)

和Win32应用程序有:

int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
Run Code Online (Sandbox Code Playgroud)

和MacOS有:

int main(int argc, char **argv, char **envp, char **apple)
Run Code Online (Sandbox Code Playgroud)

不要忘记,这main通常不是操作系统在执行程序时调用的第一件事.该main函数是运行时环境调用的函数.要执行的第一条指令的地址通常在某些元数据中声明,通常在可执行文件的开头处.

就我所知,只要只有一个,这一切都与C/C++标准相矛盾,这是有道理的,因为如果有多个操作系统,操作系统就不知道应该调用哪个.检查编译器中只有一个没有完成,它是在链接器中完成的.

  • @Xeo:这基本上是在极限上...... VS的作用是为你创建一个`main`函数,在调用你的`WinMain`函数之前做一些特定的初始化.该程序的入口点仍然是"main",只是在这种情况下它不是*your*main.它似乎与§3.6.1/ 2相矛盾*实现不应预定义主函数.*,但是如果它们可以确保它不会影响你的程序(即如果你确定`main`它使用你的版本而不是它本身也可以表现为*as-if*,这就足够了. (3认同)
  • +1等待有人提及envp ...... :-) (2认同)
  • 我想知道,MSVC可以被视为不符合wrt`WinMain`吗?由于入口函数被定义为`main` ...(除了MSVC中所有其他不兼容的东西.) (2认同)

Alo*_*ave 13

C++标准1998和2003版本的第3.6.1.2节规定:

实现不应预定义主函数.此功能不应过载.它应该具有int类型的返回类型,否则其类型是实现定义的.

进一步,

ISO C++标准(ISO/IEC 14882:1998)特别要求main返回int.它对格式良好的程序有明确的"应当"约束.

第3.6.1节2:

它的返回类型应为int,否则其类型是实现定义的.所有实现都应允许以下两个主要定义:

int main() { /* … */ }
Run Code Online (Sandbox Code Playgroud)

int main(int argc, char* argv[]) { /* … */ }
Run Code Online (Sandbox Code Playgroud)

因此main,标准允许使用哪个版本,使用哪个版本作为程序员的实现首选项.


Bil*_*eal 9

主要是在C天定义的.它的设置更符合printf的规则.考虑main作为一个varadic函数:

int main(...)
Run Code Online (Sandbox Code Playgroud)

标准说没有参数和两个指针参数是可以的.但是,如果实现想要提供更多参数,则实现可以自由地执行.

您不能拥有两个mains的原因与您printf在C程序中无法两次定义like函数的原因相同.当然,printf支持不同的参数并根据哪些参数改变它的行为,但它不会在C++的术语意义上重载.


peo*_*oro 7

标准说main不能超载.它没有被破坏,你不能拥有两个具有相同unmangled名称的函数.我想这会导致链接失败,但编译器可能希望添加显式检查以便提供更清晰的错误消息.

int main(int argc, char **argv)并且int main()应该是它的首选签名,但编译器可以自由地接受main具有不同参数的a.