Pra*_*ady 58 c signature entry-point language-lawyer function-prototypes
C中主要功能的有效签名究竟是什么?我知道:
int main(int argc, char *argv[])
Run Code Online (Sandbox Code Playgroud)
还有其他有效的吗?
pax*_*blo 68
本回答(C11)时的现行标准明确提到了这两个:
int main(void);
int main(int argc, char* argv[]);
Run Code Online (Sandbox Code Playgroud)
虽然它确实提到了"或等同"这一短语,但附有以下脚注:
因此,
C11
可以替换int
为定义为的名称typedef
,或者int
可以写为的类型argv
,等等.
此外,它还提供了更多(实现定义的)可能性.
相关部分(C11中的第5.1.2.2.1节,但此特定方面与C99相同)说明:
程序启动时调用的函数名为main.该实现声明此函数没有原型.它应该使用int的返回类型定义,并且没有参数:
Run Code Online (Sandbox Code Playgroud)int main(void) { /* ... */ }
或者有两个参数(这里称为argc和argv,虽然可以使用任何名称,因为它们是声明它们的函数的本地名称):
Run Code Online (Sandbox Code Playgroud)int main(int argc, char *argv[]) { /* ... */ }
或同等学历; 或者以某种其他实现定义的方式.
如果声明它们,main函数的参数应遵循以下约束:
值
char ** argv
应为非负值.
5.1.2.2.1
应为空指针.如果argc的值大于零,则
C99
通过main
包含的数组成员应包含指向字符串的指针,这些指针在程序启动之前由主机环境给出实现定义的值.目的是在程序启动之前从托管环境中的其他地方向程序提供信息.如果主机环境不能提供大写和小写字母的字符串,则实现应确保以小写形式接收字符串.如果值
int
大于零,则指向的字符串argc
表示程序名称;argv
如果程序名不能从主机环境获得,则应为空字符.如果值main
大于1,则argc
through 指向的字符串argv[argc]
表示程序参数.数组指向的参数
argc
和argv[0]
字符串argv[argc-1]
应由程序修改,并在程序启动和程序终止之间保留它们最后存储的值.
请注意,这适用于托管环境,您通常在C程序中看到的环境.独立环境(例如嵌入式系统)的约束要少得多,如同标准的5.1.2.1中所述:
在独立环境中(可以在没有操作系统任何好处的情况下执行C程序),程序启动时调用的函数的名称和类型是实现定义的.除了第4节要求的最小集合之外,任何可用于独立程序的库设施都是实现定义的.
Jon*_*ler 17
对于托管环境(这是正常环境),C99标准说:
5.1.2.2.1程序启动
在程序启动时调用的函数被命名
main
.该实现声明此函数没有原型.它应定义为返回类型int
且没有参数:Run Code Online (Sandbox Code Playgroud)int main(void) { /* ... */ }
或者有两个参数(这里称为
argc
和argv
,虽然可以使用任何名称,因为它们是声明它们的函数的本地名称):Run Code Online (Sandbox Code Playgroud)int main(int argc, char *argv[]) { /* ... */ }
或同等学历; 9)或以其他一些实现定义的方式.
9)因此,
int
可以替换为定义为的typedef名称int
,或者argv
可以写为 的类型char **argv
,依此类推.
C11和C18标准与C99标准基本相同.
C++ 98标准说:
3.6.1主要功能[basic.start.main]
1程序应包含一个名为main的全局函数,它是程序的指定开始.[...]
2实现不应预定义主要功能.此功能不应过载.它应该具有int类型的返回类型,否则其类型是实现定义的.所有实现都应允许以下两个主要定义:
Run Code Online (Sandbox Code Playgroud)int main() { /* ... */ }
和
Run Code Online (Sandbox Code Playgroud)int main(int argc, char* argv[]) { /* ... */ }
C++标准明确地说"它[主函数]应该具有int类型的返回类型,但是其类型是实现定义的",并且需要与C标准相同的两个签名.因此,C++标准直接不允许'void main()',尽管没有什么可以阻止非标准的符合实现允许替代(也不是标准的符合实现允许替代作为标准的扩展).
C++ 03,C++ 11,C++ 14和C++ 17标准与C++ 98基本相同.
传统上,Unix系统支持第三种变体:
int main(int argc, char **argv, char **envp) { ... }
Run Code Online (Sandbox Code Playgroud)
第三个参数是一个以null结尾的字符串指针列表,每个字符串都是一个环境变量,它有一个名称,一个等号和一个值(可能是空的).如果你不使用它,你仍然可以通过' extern char **environ;
' 进入环境.很长一段时间,它没有声明它的标题,但POSIX 2008标准现在要求它被声明<unistd.h>
.
这被C标准认可为附录J中记录的共同扩展:
J.5.1环境参数
1在托管环境中,main函数接收第三个参数,
char *envp[]
该参数指向以null结尾的指针数组char
,每个指针指向一个字符串,该字符串提供有关此程序执行环境的信息(5.1. 2.2.1).
在微软VS 2010的编译器是有趣的.该网站说:
main的声明语法是
Run Code Online (Sandbox Code Playgroud)int main();
或者,可选地,
Run Code Online (Sandbox Code Playgroud)int main(int argc, char *argv[], char *envp[]);
或者,可以将
main
和wmain
函数声明为返回void
(无返回值).如果声明main
或wmain
返回void,则无法使用return语句将退出代码返回到父进程或操作系统.要在声明为main
或返回时返回退出代码,必须使用该函数.wmain
void
exit
我不清楚当一个程序void main()
退出时会发生什么(退出代码返回到父代或o/s)- 并且MS网站也是静默的.
有趣的是,MS没有规定main()
C和C++标准所要求的双参数版本.它只规定了一个三参数形式,其中第三个参数是char **envp
指向环境变量列表的指针.
Microsoft页面还列出了一些其他选项 - wmain()
它们需要广泛的字符串,还有更多.
此页面的Microsoft VS 2005版本不void main()
作为替代列出.Microsoft VS 2008以后的版本可以.
int main()
一样的int main(void)
吗?有关详细分析,请参阅我在C和C++中应main()
返回的内容的答案的结尾.(看来,我一度认为,这个问题被称为C++,即使它不和从来没有.在C++中,有没有区别int main()
和int main(void)
和int main()
是地道的C++).
在C中,两种符号之间存在差异,但您只能在深奥的情况下注意到它.具体来说,如果您main()
从自己的代码中调用该函数,则会有所不同,您可以在C中执行该函数,并且不允许在C++中执行该函数.
该int main()
符号不提供一个原型main()
,但只有事项,如果你递归调用它.有了int main()
,您可能稍后(在同一个函数中,或在另一个函数中)编写int rc = main("absolute", "twaddle", 2):
并且正式编译器不应该抱怨拒绝编译代码,尽管它可能合法地抱怨(警告您)它(并使用-Werror
与GCC会将警告转换为错误).如果你使用int main(void)
,后续调用main()
应该生成一个错误 - 你说该函数没有参数,但试图提供三个.当然,main()
在声明或定义它之前,你不能合法地调用它(除非你仍在使用C90语义) - 并且实现没有声明原型main()
.注意:C11标准说明了两者int main()
和int main(void)
不同的例子 - 两者都在C中有效,即使它们之间存在细微差别.
POSIX支持execve()
,反过来支持
int main(int argc, char *argv[], char *envp[])
Run Code Online (Sandbox Code Playgroud)
添加的参数是环境,即NAME = VALUE形式的字符串数组.
http://en.wikipedia.org/wiki/Main_function_(programming)#C_and_C.2B.2B
除了通常int main(int argc, char *argv[])
和POSIX之外int main(int argc, char **argv, char **envp)
,在Mac OS X上也支持
int main(int argc, char* argv[], char* envp[], char* apple[]);
Run Code Online (Sandbox Code Playgroud)
当然它只是Mac版.
在Windows上有
int wmain(int argc, wchar_t* argv[], wchar_t* envp[]);
Run Code Online (Sandbox Code Playgroud)
作为Unicode(实际上是宽字符)变体.当然也有WinMain
.