标准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
大于一,字符串由指向argv[1]
通过argv[argc-1]
表示该程序的参数。
- 数组所指向的参数
argc
和argv
字符串argv
应可由程序修改,并在程序启动和程序终止之间保留其最后存储的值。
10)因此,int
可以用定义为的typedef名称代替int
,或者argv
可以将其类型写为
char **argv
,等等。
C99或C11中的程序终止
从返回的值main()
以实现定义的方式传输到“环境”。
5.1.2.2.3程序终止
1如果main
函数的返回类型是与兼容的类型int
,则从初始调用到main
函数的返回等同于以exit
函数返回的值main
作为参数来调用函数;11)到达}
终止
main
函数的值返回0。如果返回类型与不兼容int
,则未指定返回主机环境的终止状态。
11)根据6.2.4,main
在前一种情况下,声明具有自动存储期限的对象的生存期将结束,即使后者没有。
请注意,这0
被强制为“成功”。如果愿意,可以使用EXIT_FAILURE
and EXIT_SUCCESS
from <stdlib.h>
,但是0已被确立,1也是如此。另请参见大于255的退出代码-可能吗?。
在C89中(因此在Microsoft C中),没有关于该main()
函数返回但未指定返回值的情况的声明。因此,它导致不确定的行为。
7.22.4.4 exit
功能
¶5最后,控制权返回到主机环境。如果值为status
0或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
是非零这些参数应在提供argv[0]
通过argv[argc-1]
作为指针指向空终止多字节串的初始字符(NTMBSs)(17.5.2.1.4.2)和argv[0]
应为指针NTMBS的初始字符,表示用来名称调用程序或""
。的值argc
应为非负数。的值argv[argc]
应为0。[注:建议在之后添加任何其他(可选)参数argv
。—尾注]
¶3该功能main
不得在程序内使用。的链接(3.5)由main
实现定义。[...]
¶5main中的return语句的作用是保留main函数(销毁具有自动存储持续时间的所有对象)并std::exit
以return值作为参数进行调用。如果控制在没有遇到return语句的情况下到达了main的末尾,则其结果是执行
return 0;
C ++标准明确表示“ [[主函数]应该具有type的返回类型int
,但否则其类型是实现定义的”,并且需要与C标准相同的两个签名作为支持选项。因此,C ++标准直接不允许使用“ void main()”,尽管它无法停止允许替代方法的非标准实现。请注意,C ++禁止用户调用main
(但C标准不禁止)。
有§18.5的段开始和终止在C ++ 11标准,其是与从§7.22.4.4段落的exit
功能在C11标准(上面引述的),除了一个脚注(其简单地文档EXIT_SUCCESS
和EXIT_FAILURE
定义在<cstdlib>
)。
标准C —通用扩展
传统上,Unix系统支持第三个变体:
int main(int argc, char **argv, char **envp) { ... }
第三个参数是一个以空字符结尾的字符串指针列表,每个字符串都是一个环境变量,该环境变量具有名称,等号和值(可能为空)。如果不使用它,您仍然可以通过' extern char **environ;
' 访问环境。该全局变量在POSIX中是唯一的,因为它没有声明它的标头。
这是C标准认可的通用扩展,记录在附件J中:
J.5.1环境参数
¶1在托管环境中,主函数接收第三个参数,char *envp[]
该参数指向以NULL终止的指针数组char
,每个指针均指向一个字符串,该字符串提供有关此程序执行环境的信息(5.1。 2.2.1)。
微软C
在微软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()
退出时会发生什么(退出代码返回给父代或OS),而MS网站也保持沉默。
有趣的是,MS并未规定main()
C和C ++标准所需的两个参数的版本。它仅规定了三个参数形式,其中第三个参数为char **envp
,它是指向环境变量列表的指针。
Microsoft页面还列出了其他一些替代方法- wmain()
需要宽字符串,还有其他一些替代方法。
此页面的Microsoft Visual Studio 2005版本未列出。从Microsoft Visual Studio 2008开始的版本都可以。void main()
标准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独立实施[遵从性]
定义了两种实现:托管和独立(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>
int main()
在C中使用呢?
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;
}