命名空间
变体
操作

主函数

来自 cppreference.com
< cpp‎ | 语言
 
 
C++ 语言
 
 

程序应包含一个名为 main 的全局函数,它是托管环境中程序的指定入口点。它应具有以下形式之一

int main() { 主体 } (1)
int main(int argc, char* argv[]) { 主体 } (2)
int main(/* 实现定义的 */) { 主体 } (3)
1) 独立于环境提供的参数运行的 main 函数。
2) 接受环境提供的参数的 main 函数。
argcargv 的名称是任意的,参数类型的表示也是任意的: int main(int ac, char** av) 同样有效。
3) 实现定义类型的 main 函数,返回 int
C++ 标准建议实现定义的 main 函数将额外的 (可选) 参数放在 argv 之后。
argc - 表示从运行程序的环境传递给程序的参数数量的非负值。
argv - 指向包含 argc + 1 个指针的数组的第一个元素的指针,其中最后一个指针为空,而前面的指针 (如果有) 指向 以空字符结尾的多字节字符串,这些字符串表示从执行环境传递给程序的参数。如果 argv[0] 不是空指针 (或等效地,如果 argc > 0),则它指向一个字符串,该字符串表示用于调用程序的名称,或指向一个空字符串。
主体 - main 函数的主体。

内容

[编辑] 说明

main 函数在程序启动时调用,在 初始化 具有静态 存储持续时间 的非局部对象之后。它是托管环境 (即,使用操作系统) 中执行的程序的指定入口点。独立程序 (引导加载程序、操作系统内核等) 的入口点是实现定义的。

main 函数的双参数形式的参数允许从执行环境传递任意多字节字符字符串(通常称为命令行参数),指针 argv[1] .. argv[argc - 1] 指向每个字符串中的第一个字符。 argv[0](如果非空)是指向表示调用程序本身所用名称的空终止多字节字符串的第一个字符的指针(或空字符串 "",如果执行环境不支持此功能)。这些字符串是可修改的,尽管这些修改不会传播回执行环境:例如,它们可以与 std::strtok 一起使用。argv 指向的数组的大小至少为 argc + 1,最后一个元素 argv[argc] 保证为空指针。

main 函数具有以下几个特殊属性

1) main 函数体不需要包含 return 语句:如果控制流到达 main 的末尾而没有遇到 return 语句,则其效果等同于执行 return 0;
2) 执行 return(或到达 main 的末尾时的隐式 return)等效于首先正常离开函数(这将销毁具有自动存储期的对象),然后调用 std::exit,其参数与 return 的参数相同(std::exit 然后销毁静态对象并终止程序)。

main 函数有一些限制(违反这些限制会导致程序格式不正确)

1) 它不能在程序中的任何地方被 命名
a) 特别地,它不能递归调用
b) 它的地址不能被获取
c) 它不能在 typeid 表达式 decltype 指定符中(自 C++11 起) 使用
2) 它不能预定义,也不能重载:实际上,全局命名空间中的名称 main 保留用于函数(尽管它可以用来命名类、命名空间、枚举,以及非全局命名空间中的任何实体,但名为 main 的实体不能在任何命名空间中以 C 语言链接 声明)。
3) 它不能 定义为已删除或(自 C++11 起) 用任何语言链接 constexpr(自 C++11 起)consteval(自 C++20 起)inlinestatic 声明。
4) main 函数的返回类型不能推断(auto main() {...} 不允许)。
(自 C++14 起)
5) main 函数不能是 协程
(自 C++20 起)
6) main 函数不能附加到命名 模块
(自 C++20 起)

[edit] 备注

如果 main 函数用 函数 try 定义,则由静态对象的析构函数抛出的异常(这些对象由隐式的 std::exit 销毁)不会被 捕获

将 OS 命令行中给出的参数转换为 argv 引用的多字节字符数组的方式可能涉及实现定义的处理

一种非常常见的实现定义的 main() 形式有第三个参数(除了 argcargv),类型为 char**,指向 指向执行环境变量的数组的指针

[edit] 示例

演示如何告知程序在哪里找到它的输入以及在哪里写入结果。
可能的调用:./convert table_in.dat table_out.dat

#include <cstdlib>
#include <iomanip>
#include <iostream>
 
int main(int argc, char *argv[])
{
    std::cout << "argc == " << argc << '\n';
 
    for (int ndx{}; ndx != argc; ++ndx)
        std::cout << "argv[" << ndx << "] == " << std::quoted(argv[ndx]) << '\n';
    std::cout << "argv[" << argc << "] == "
              << static_cast<void*>(argv[argc]) << '\n';
 
    /* ... */
 
    return argc == 3 ? EXIT_SUCCESS : EXIT_FAILURE; // optional return value
}

可能的输出

argc == 3
argv[0] == "./convert"
argv[1] == "table_in.dat"
argv[2] == "table_out.dat"
argv[3] == 0

[edit] 参考文献

扩展内容
  • C++23 标准 (ISO/IEC 14882:2024)
  • 6.9.3.1 main 函数 [basic.start.main]

[edit] 缺陷报告

以下行为变更的缺陷报告已追溯应用到先前发布的 C++ 标准。

DR 应用于 发布的行为 正确行为
CWG 1003 C++98 支持的 main 参数名称过于受限 所有有效的参数
名称都受支持
CWG 1886 C++98 main 函数可以声明为语言链接 禁止
CWG 2479 C++20 main 函数可以声明为 consteval 禁止
CWG 2811 C++98 N3214 之后是否使用 main 函数尚不清楚 当命名时,它被认为是已使用的

[edit] 另见

C 文档 针对 main 函数