main()应该在C和C ++中返回什么?
什么是在C和C ++中定义main()
函数的正确(最有效的)方法 - int main()
或void main()
- 为什么? 如果int main()
则return 1
或return 0
?
这个问题有很多重复,包括:
main()
函数的有效签名是什么? main()
函数的返回类型 void main()
和int main()
之间的区别? main()
在C ++中的签名 main()
的正确声明? - 对于C ++,确实有非常好的答案。 main()
函数的样式 main()
方法的返回类型 int main()
vs void main()
in C 有关:
int main(int argc, char **argv)
int main(int argc, char *argv[])
char *envp[]
作为main()
便携式的第三个参数吗? int main()
函数是否必须在所有编译器中返回一个值? main()
函数的类型留给用户定义? int main(){}
编译? main()
在C ++ 14中的法律定义? main
的返回值应指示程序如何退出。 正常退出通常由来自main
返回值0表示。 异常终止通常以非零返回来表示,但对于如何解释非零代码没有标准。 同样如其他人所指出的, void main()
被C ++标准明确禁止,不应该被使用。 有效的C ++ main
签名是:
int main()
和
int main(int argc, char* argv[])
相当于
int main(int argc, char** argv)
值得注意的是,在C ++中, int main()
可以不带返回值,此时它默认返回0.这对于C99程序也是如此。 是否应该省略返回0是否可以辩论。 有效的C程序主签名的范围要大得多。
而且, main
功能的效率不是问题。 它只能根据C ++标准进入并留下一次(标记程序开始和终止)。 对于C来说,情况是不同的,允许重新输入main()
,但应该可以避免。
接受的答案似乎是针对C ++的,所以我想我会添加一个与C相关的答案,这在几个方面有所不同。
ISO / IEC 9899:1989(C90):
main()
应该声明为:
int main(void)
int main(int argc, char **argv)
或同等学历。 例如, int main(int argc, char *argv[])
等价于第二个。 此外,因为它是默认值,所以可以省略int
返回类型。
如果一个实现允许它, main()
可以用其他方式声明,但这会使程序实现定义,不再严格符合。
该标准定义了3个严格符合(即不依赖于实现定义的行为)的返回值: 0
和EXIT_SUCCESS
用于成功终止, EXIT_FAILURE
用于不成功终止。 任何其他值都是非标准的,并且定义了实现。 main()
在最后必须有一个显式的return
语句来避免未定义的行为。
最后,从标准的角度来看,从程序中调用main()
并没有错。
ISO / IEC 9899:1999(C99):
对于C99,除了以下内容外,其他内容与上述相同:
int
返回类型不能省略。 main()
的return语句。 如果你这样做,并且main()
完成,则隐式return 0
。 标准C - 托管环境
对于托管环境(这是正常的),C11标准(ISO / IEC 9899:2011)说:
5.1.2.2.1程序启动
程序启动时调用的函数名为main
。 该实现没有声明这个函数的原型。 它应该用返回类型int
和不带参数来定义:
int main(void) { /* ... */ }
或者带有两个参数(这里称为argc
和argv
,尽管可以使用任何名称,因为它们是声明它们的函数的本地):
int main(int argc, char *argv[]) { /* ... */ }
或等同物; 10)或以某种其他实施方式定义的方式。
如果声明它们,则主函数的参数应遵守以下约束条件:
argc
的值应该是非负的。 argv[argc]
应该是一个空指针。 argc
的值大于零,则包含argv[0]
至argv[argc-1]
的数组成员应包含指向字符串的指针,这些字符串在程序启动之前由主机环境给定实现定义的值。 其目的是向程序提供在程序启动之前从托管环境中的其他地方确定的信息。 如果主机环境不能提供大写和小写字母的字符串,则实现应确保字符串以小写字母接收。 argc
的值大于零,则由argv[0]
指向的字符串表示程序名称; 如果程序名称在主机环境中不可用,则argv[0][0]
应为空字符。 如果argc
的值大于1, argv[1]
至argv[argc-1]
指向的字符串表示程序参数。 argc
和argv
以及argv
数组所指向的字符串应该可以通过程序修改,并在程序启动和程序终止之间保留最后存储的值。 10)因此, int
可以被定义为int
的typedef名称替代,或者argv
的类型可以被写为char **argv
,依此类推。
程序在C99或C11中终止
从main()
返回的值以实现定义的方式传输到“环境”。
5.1.2.2.3程序终止
1如果main
函数的返回类型是与int
兼容的类型,则从初始调用返回到main
函数相当于使用main
函数返回的值作为参数来调用exit
函数; 11)到达}
终止main
函数返回值0.如果返回类型与int
不兼容,则返回到主机环境的终止状态未指定。
11)根据6.2.4,在main
声明自动存储时间的物体的寿命将在前一种情况下结束,即使在后一种情况下它们不存在的情况下。
请注意, 0
被强制为“成功”。 如果您愿意,您可以使用<stdlib.h>
EXIT_FAILURE
和EXIT_SUCCESS
,但是0已经很好建立,所以是1.另请参阅退出代码大于255 - 可能吗?
在C89中(因此在C中),没有关于main()
函数返回时会发生什么的声明,但没有指定返回值; 它因此导致未定义的行为。
7.22.4.4 exit
功能
¶5最后,控制权返回到主机环境。 如果status
值为零或EXIT_SUCCESS
,则返回状态成功终止的实现定义形式。 如果status
值为EXIT_FAILURE
,则返回状态不成功终止的实现定义形式。 否则,返回的状态是实现定义的。
标准C ++ - 托管环境
C ++ 11标准(ISO / IEC 14882:2011)说:
3.6.1主要功能[basic.start.main]
¶1程序应包含一个名为main的全局函数,它是程序的指定开始。 [...]
¶2实现不应该预定义主函数。 该功能不得超载。 它应该有一个类型为int的返回类型,否则其类型是实现定义的。 所有的实现都应该允许main的以下两个定义:
int main() { /* ... */ }
和
int main(int argc, char* argv[]) { /* ... */ }
在后一种形式中, argc
应是从程序运行环境传递给程序的参数的数量。 如果argc
不为零,那么这些参数将作为指向NULL结尾多字节字符串(NTMBS)(17.5.2.1.4.2)和argv[0]
的初始字符的指针,以argv[0]
至argv[argc-1]
形式提供指向NTMBS的初始字符的指针,表示用于调用程序的名称或""
。 argc
的值应该是非负的。 argv[argc]
的值应为0. [注意:建议在argv
之后添加任何其他(可选)参数。 - 注意]
¶3函数main
不能在程序中使用。 main
的链接(3.5)是实现定义的。 [...]
¶5main中的return语句具有离开main函数(销毁具有自动存储持续时间的任何对象)并以返回值作为参数调用std::exit
效果。 如果控制到达主的结尾而没有遇到return语句,则效果是执行
return 0;
C ++标准明确地说“它[主函数]应该有一个类型为int
的返回类型,否则它的类型就是实现定义的”,并且需要与作为选项支持的C标准相同的两个签名。 因此,C ++标准直接不允许使用'void main()',尽管没有办法阻止非标准的实现允许其他选择。 请注意,C ++禁止用户调用main
(但C标准不)。
在C ++ 11标准中有一段§18.5 开始和终止 ,与§7.22.4.4中的段落相同。C11标准中的exit
函数 (上面引用的)除了脚注外(它只是记录了EXIT_SUCCESS
和EXIT_FAILURE
在<cstdlib>
中定义)。
标准C - 公共扩展
传统上,Unix系统支持第三种变体:
int main(int argc, char **argv, char **envp) { ... }
第三个参数是一个以空字符结尾的字符串指针列表,每个字符串都是一个具有名称,等号和值(可能为空)的环境变量。 如果你不使用这个,你仍然可以通过' extern char **environ;
'来获得extern char **environ;
”。 很长一段时间,它没有声明它的头文件,但POSIX 2008标准现在要求它在<unistd.h>
声明。
这被C标准认可为一个通用扩展,记录在附录J中:
J.5.1环境参数
¶1在托管环境中,主函数接收第三个参数char *envp[]
,该参数指向以char
为空的终止指针数组,每个指向一个字符串,该字符串提供有关此执行的环境的信息(5.1.2.2.1)。
微软C
Microsoft VS 2010编译器很有趣。 该网站说:
main的声明语法是
int main();
或者可选地,
int main(int argc, char *argv[], char *envp[]);
或者, main
和wmain
函数可以声明为返回void
(无返回值)。 如果将main
或wmain
声明为返回void,则无法使用return语句将退出代码返回给父进程或操作系统。 要将main
或wmain
声明为void
时返回退出代码,您必须使用exit
函数。
当有一个带有void main()
的程序确实退出时,我不清楚发生了什么(退出代码返回给父级或操作系统),而且MS网站也是无声的。
有趣的是,MS并没有规定C和C ++标准要求的main()
的双参数版本。 它只规定了一个三参数形式,其中第三个参数是char **envp
,指向一个环境变量列表的指针。
微软的网页还列出了一些其他的选择 - wmain()
,它需要宽字符字符串等等。
此页面的Microsoft Visual Studio 2005版本没有列出void main()
作为替代方案。 Microsoft Visual Studio 2008以后的版本可以。
标准C-独立环境
如前所述,上述要求适用于托管环境。 如果您正在使用独立式环境(这是托管环境的替代方案),那么标准就更不用说了。 对于独立环境,在程序启动时调用的函数不需要被称为main
并且其返回类型没有限制。 该标准说:
5.1.2执行环境
定义了两种执行环境:独立式和托管式。 在这两种情况下,当执行环境调用指定的C函数时都会发生程序启动。 在程序启动之前,所有具有静态存储持续时间的对象都应该被初始化(设置为它们的初始值)。 这种初始化的方式和时间在其他方面没有说明。 程序终止将控制权交还给执行环境。
5.1.2.1独立环境
在一个独立的环境中(C程序的执行可能没有任何操作系统的好处),程序启动时调用的函数的名称和类型是实现定义的。 任何独立程序提供的图书馆设施,除第4条要求的最小集合外,都是实现定义的。
程序终止在独立环境中的影响是由实现定义的。
第4条一致性的交叉引用是指:
¶5严格符合的程序只能使用本标准中规定的语言和库的特征.3)不得产生取决于任何未指定,未定义或实现定义的行为的输出,并且不得超过任何最小实现限制。
¶6两种形式的一致性实施是托管和独立的。 符合托管的实施应接受任何严格符合的程序。 符合独立实施应接受任何严格符合程序,其中使用库条款(第7条)中指定的功能仅限于标准头文件<float.h>
, <iso646.h>
, <limits.h>
, <stdalign.h>
, <stdarg.h>
, <stdbool.h>
, <stddef.h>
, <stdint.h>
和<stdnoreturn.h>
。 符合的实现可以有扩展(包括附加的库函数),只要它们不改变任何严格符合的程序的行为.4)
¶7一致性程序是符合实现的可接受程序。5)
3)严格符合规范的程序可以使用条件特征(见6.10.8.3),前提是使用相关宏指令的适当条件包含预处理指令来保护使用。 例如:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
/* ... */
fesetround(FE_UPWARD);
/* ... */
#endif
4)这意味着符合的实施不会保留本标准中明确保留的标识符以外的标识符。
5)严格遵守的程序旨在最大限度地兼容实施。 符合的程序可能取决于符合实施的不可移植的特征。
值得注意的是,实际上定义了任何函数的独立环境所需的唯一头文件是<stdarg.h>
(甚至这些头文件也可能 - 通常是 - 只是宏)。
标准C ++ - 独立环境
就像C标准可以识别托管环境和独立环境一样,C ++标准也是如此。 (来自ISO / IEC 14882:2011的引文。)
1.4执行合规性[intro.compliance]
¶7定义了两种实现:托管实现和独立实现。 对于托管实现,本国际标准定义了一组可用的库。 独立实现可以在没有操作系统好处的情况下执行,并且有一个实现定义的库集合,其中包含某些语言支持库(17.6.1.3)。
¶8一致性实现可能具有扩展(包括附加的库函数),只要它们不会改变任何格式良好的程序的行为。 根据本国际标准,需要实施诊断使用不合格的扩展程序。 但是,他们这样做可以编译和执行这些程序。
¶9每个实施应包括确定所有有条件支持的构造的文档,它不支持并定义所有特定场所的特性.3
3)该文档还定义了实现定义的行为; 见1.9。
17.6.1.3独立实现[compliance]
定义了两种实现:托管式和独立式(1.4)。 对于托管实现,本国际标准描述了可用标题集。
独立实现有一个实现定义的头文件集。 该组至少应包括表16中所示的标题。
头文件<cstdlib>
的提供版本至少要声明函数abort
, atexit
, at_quick_exit
, exit
和quick_exit
(18.5)。 本表中列出的其他标题应符合与托管实施相同的要求。
表16 - 用于独立实现的C ++头文件
Subclause Header(s)
<ciso646>
18.2 Types <cstddef>
18.3 Implementation properties <cfloat> <limits> <climits>
18.4 Integer types <cstdint>
18.5 Start and termination <cstdlib>
18.6 Dynamic memory management <new>
18.7 Type identification <typeinfo>
18.8 Exception handling <exception>
18.9 Initializer lists <initializer_list>
18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool>
20.9 Type traits <type_traits>
29 Atomics <atomic>
在C中使用int main()
怎么样?
C11标准的标准§5.1.2.2.1显示了首选符号 - int main(void)
- 但在标准中也有两个示例显示int main()
:§6.5.3.4¶8和§6.7.6.3 ¶20。 现在,重要的是要注意,例子不是'规范'的。 它们只是说明性的。 如果示例中存在错误,它们不会直接影响标准的正文。 也就是说,它们强烈地表示了预期的行为,所以如果标准在示例中包含int main()
,则表明int main()
不是被禁止的,即使它不是首选符号。
6.5.3.4 sizeof
和_Alignof
运算符
...
¶8示例3在此示例中,计算可变长度数组的大小并从函数返回:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}
链接地址: http://www.djcxy.com/p/4909.html