在C和C中定义 main()
函数的正确(最有效)方法是什么 - int main()
或 void main()
- 为什么?如果 int main()
那么 return 1
或 return 0
?
这个问题有很多重复,包括:
-
What is the proper declaration of main()? - 对于C,确实有一个非常好的答案 .
有关:
在C和C中定义 main()
函数的正确(最有效)方法是什么 - int main()
或 void main()
- 为什么?如果 int main()
那么 return 1
或 return 0
?
这个问题有很多重复,包括:
What is the proper declaration of main()? - 对于C,确实有一个非常好的答案 .
有关:
18 回答
如果您确实遇到与从流程返回整数的效率相关的问题,则应该避免多次调用该流程,以使此返回值成为问题 .
如果你这样做(多次调用一个进程),你应该找到一种方法将你的逻辑直接放在调用者或DLL文件中,而不为每个调用分配一个特定的进程;在这种情况下,多个流程分配会为您带来相关的效率问题 .
详细地说,如果您只想知道返回0是否比返回1更高效或更低效率,在某些情况下它可能取决于编译器,但一般来说,假设它们是从同一源(本地,字段,常量,嵌入式)读取的在代码,功能结果等中)它需要完全相同的时钟周期数 .
操作系统可以使用返回值来检查程序的关闭方式 .
返回值0通常意味着在大多数操作系统中都可以(无论如何我都能想到) .
当您自己调用进程时,也可以检查它,并查看程序是否已正确退出并完成 .
它只是一个编程约定 NOT .
main()
的返回值显示程序退出的方式 . 如果返回值为zero
则表示执行成功,而任何非零值都表示执行中出现问题 .返回0应告诉程序员程序已成功完成作业 .
返回的内容取决于您要对可执行文件执行的操作 . 例如,如果您使用带有命令行shell的程序,则需要返回0表示成功,而非零表示失败 . 然后,您将能够使用带有条件处理的shell中的程序,具体取决于代码的结果 . 您还可以根据您的解释分配任何非零值,例如,对于严重错误,不同的程序出口点可以终止具有不同退出值的程序,并且可供调用shell使用,该调用shell可以通过检查返回的值来决定要执行的操作 . 如果代码不打算与shell一起使用,并且返回的值不会打扰任何人,那么它可能会被省略 . 我个人使用签名
int main (void) { .. return 0; .. }
请注意,C和C标准定义了两种实现:独立和托管 .
允许的表格1:
评论:
前两个被明确地声明为允许的形式,其他两个被隐式允许,因为C90允许返回类型和函数参数的“隐式int” . 不允许其他形式 .
允许任何形式或名称的主要2 .
允许的表格3:
评论:
C99已删除"implicit int",因此
main()
不再有效 .引入了一个奇怪的,含糊不清的句子"or in some other implementation-defined manner" . 这可以解释为“
int main()
的参数可以变化" or as " main可以具有任何实现定义的形式” .一些编译器选择以后一种方式解释标准 . 可以说,人们不能轻易地通过引用标准本身来说明它们并不严格遵守,因为它是模棱两可的 .
然而,允许完全狂野形式的
main()
可能(?)不是这个新句子的意图 . C99基本原理(非规范性)意味着该句子指的是int main
4的附加参数 .然而,托管环境程序终止的部分继续讨论main不返回int 5的情况 . 虽然该部分不是规范main应该如何声明,但它肯定意味着main可以在完全实现定义中声明甚至在托管系统上的方式 .
允许任何形式或名称的主要6 .
允许的表格7:
允许任何形式或名称的主要8 .
请注意,
int main()
从未作为任何上述版本中C的任何托管实现的有效表单列出 . 在C中,与C不同,()
和(void)
具有不同的含义 . 前者是一种过时的功能,可以从语言中删除 . 请参阅C11未来语言方向:允许的表格9:
评论:
请注意第一种形式的空括号 . 在这种情况下,C和C是不同的,因为在C中这意味着该函数不带参数 . 但在C语中,这意味着它可能需要任何参数 .
启动时调用的函数名称是实现定义的 . 如果它被命名为
main()
,则必须遵循所述的表格10:允许的表格11:
评论:
标准的文本已经改变,但它具有相同的含义 .
启动时调用的函数名称是实现定义的 . 如果它名为
main()
,则必须遵循所述的表格12:References
本节与上面引用的C99相同 .
本节与上面引用的C99相同 .
该部分与上面引用的C 03相同 .
省略返回0
当C或C程序到达
main
的末尾时,编译器将自动生成返回0的代码,因此不需要在main
的末尾显式地放置return 0;
.Note: 当我提出这个建议时,它依赖于标准明确支持的编译器行为是安全且有用的 . 对于C,自C99起;见ISO / IEC 9899:1999第5.1.2.2.3节:
对于C,自1998年的第一个标准;见ISO / IEC 14882:1998第3.6.1节:
从那时起(C99和C98)这两个标准的所有版本都保持了相同的想法 . 我们依赖于C中自动生成的成员函数,很少有人在
void
函数的末尾编写显式的return;
语句 . 忽略的原因似乎归结为"it looks weird" . 如果像我一样,你对改变C标准read this question的理由感到好奇 . 另请注意,在20世纪90年代早期,这被认为是"sloppy practice",因为它当时是未定义的行为(尽管得到广泛支持) .所以我主张省略它;其他人不同意(通常是激烈的!)在任何情况下,如果你遇到省略它的代码,你就会知道标准明确支持它,你就会知道它意味着什么 .
_903885_在C89和K&R C中未指定的返回类型默认为'int` .
int main()
中写入return语句,则结束{
将默认返回0 .父进程将收到
return 0
或return 1
. 在shell中它进入shell变量,如果你运行程序形成一个shell而不使用该变量,那么你不必担心main()
的返回值 .见How can I get what my main function has returned? .
这样你就可以看到它是变量
$?
,它接收main()
的返回值的最低有效字节 .在Unix和DOS脚本中,通常会返回
return 0
成功和非零错误 . 这是Unix和DOS脚本使用的标准,用于查找程序发生的情况并控制整个流程 .标准C - 托管环境
对于托管环境(这是正常的环境),C11标准(ISO / IEC 9899:2011)说:
程序在C99或C11中终止
从
main()
返回的值以实现定义的方式传输到'environment' .请注意,
0
被强制为'success' . 如果您愿意,可以使用<stdlib.h>
和EXIT_SUCCESS
,但是0已经 Build ,因此是1.另请参阅Exit codes greater than 255 — possible? .在C89中(因此在Microsoft C中),没有声明如果
main()
函数返回但未指定返回值会发生什么;因此它会导致未定义的行为 .标准C - 托管环境
C 11标准(ISO / IEC 14882:2011)说:
C标准明确地说“它[主函数]应该具有类型为
int
的返回类型,但是其类型是实现定义的”,并且需要与C标准相同的两个签名作为选项支持 . 所以C标准直接不允许'void main()',尽管它没有办法阻止非标准实现允许替代方案 . 请注意,C禁止用户调用main
(但C标准没有) .C11标准中有一段§18.5 Start and termination 与C11标准(上面引用)中的第7.22.4.4段 The exit function 中的段落相同,除了脚注(其中只是文件
EXIT_SUCCESS
和EXIT_FAILURE
在<cstdlib>
中定义) .标准C - 通用扩展
传统上,Unix系统支持第三种变体:
第三个参数是一个以空字符结尾的字符串指针列表,每个字符串都是一个环境变量,它有一个名称,一个等号和一个值(可能是空的) . 如果你不使用它,你仍然可以通过'
extern char **environ;
'进入环境 . 很长一段时间,它没有声明它的 Headers ,但POSIX 2008标准现在要求它在<unistd.h>
中声明 .这被C标准认可为附件J中记录的共同扩展:
Microsoft C
Microsoft VS 2010编译器很有趣 . 该网站说:
我不清楚是什么当具有
void main()
的程序确实退出时,会发生(退出代码返回到父代或操作系统) - 并且MS网站也是静默的 .有趣的是,MS没有规定C和C标准要求的双参数版本
main()
. 它只规定了一个三参数形式,其中第三个参数是char **envp
,一个指向环境变量列表的指针 .Microsoft页面还列出了一些其他选择 -
wmain()
,它采用宽字符串,还有更多 .this page的Microsoft Visual Studio 2005版本未列出
void main()
作为替代 . 来自Microsoft Visual Studio 2008的versions确实如此 .标准C - 独立环境
如前所述,上述要求适用于托管环境 . 如果您正在使用独立环境(这是托管环境的替代方案),那么标准就更不用说了 . 对于独立环境,在程序启动时调用的函数不需要调用
main
,并且对其返回类型没有约束 . 标准说:对第4条一致性的交叉引用是指:
值得注意的是,实际定义任何函数的独立环境所需的唯一标头是
<stdarg.h>
(甚至可能是 - 通常只是宏) .标准C - 独立环境
正如C标准同时承认托管和独立环境一样,C标准也是如此 . (引自ISO / IEC 14882:2011 . )
<ciso646> 18.2类型<cstddef> 18.3实施属性<cfloat> <limits> <climits> 18.4整数类型<cstdint> 18.5启动和终止<cstdlib> 18.6动态内存管理<新> 18.7类型标识<typeinfo> 18.8异常处理<exception> 18.9初始化列表<initializer_list> 18.10其他运行时支持<cstdalign> <cstdarg> <cstdbool> 20.9类型特征<type_traits> 29原子学<原子>
在C中使用int main()怎么样?
C11标准的标准§5.1.2.2.1显示了首选符号 -
int main(void)
- 但标准中还有两个示例显示int main()
:§6.5.3.4 ¶8和§6.7.6.3 ¶20 . 现在,重要的是要注意示例不是'normative';它们只是说明性的 . 如果示例中存在错误,则它们不会直接影响标准的主要文本 . 也就是说,它们强烈表明预期的行为,因此如果标准中包含int main()
,则表明int main()
不被禁止,即使它不是首选符号 .size_t fsize3(int n)
{
char b [n 3]; //可变长度数组
返回sizeof b; //执行时间sizeof
}
int main()
{
size_t大小;
size = fsize3(10); // fsize3返回13
返回0;
}
我的印象是标准指定main不需要返回值,因为成功的返回是基于操作系统的(零合一可能是成功或失败在另一个),因此没有返回是一个提示编译器插入成功返回本身 .
但是我通常会返回0 .
接受的答案似乎是针对C的,所以我想我会添加一个与C有关的答案,这在某些方面有所不同 .
ISO / IEC 9899:1989(C90):
main()
应声明为:或同等学历 . 例如,
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
.请记住,即使您返回int,某些操作系统(Windows)也会将返回值截断为单个字节(0-255) .
那些单词在一个独立的环境中,有一种普遍正确的方式来声明
main()
,那就像返回int一样 .这不是
main()
应该返回的,这是main()
返回的内容 .main()
当然是别人打电话的功能 . 您无法控制调用main()
的代码 . 因此,您必须使用类型正确的签名声明main()
以匹配其调用者 . 你根本不应该问自己什么是更好或更差的风格,或类似的东西,因为答案是已经完全明确地为您定义了C和C标准 . 跟着他们 .0表示成功,非零表示失败 . 同样,不是你需要(或得到)选择的东西:它是由你应该遵守的界面定义的 .
main
的返回值应指示程序如何退出 . 正常退出通常由main
的0返回值表示 . 异常退出通常通过非零返回来表示,但是没有关于如何解释非零代码的标准 . 另外,如其他人所述,C标准明确禁止void main()
,不应使用 . 有效的Cmain
签名是:和
这相当于
值得注意的是,在C中,
int main()
可以没有返回值,此时它默认返回0.对于C99程序也是如此 . 是否应该省略return 0
是否可以辩论 . 有效的C程序主要签名的范围要大得多 .此外,效率不是
main
功能的问题 . 它只能根据C标准输入和保留一次(标记程序的启动和终止) . 对于C,情况不同并且允许重新输入main()
,但应该避免 .成功时返回0,错误返回非零 . 这是UNIX和DOS脚本使用的标准,用于查找程序发生的情况 .
这是一个关于返回代码使用的小型演示......
使用Linux终端提供的各种工具时,可以使用返回代码,例如在完成该过程后进行错误处理 . 想象一下,存在以下文本文件myfile:
执行grep命令时,将创建一个进程 . 一旦通过(并且没有中断),它将返回0到255之间的一些代码 . 例如:
如果你这样做
你会得到一个0.为什么?因为grep找到匹配并返回退出代码0,这是退出成功的通常值 . 让我们再次检查它,但是有些东西不在我们的文本文件中,因此找不到匹配项:
由于grep未能将令牌“foo”与我们文件的内容匹配,因此返回码为1(这是发生故障时的常见情况,但如上所述,您有大量值可供选择) .
现在下面的bash脚本(只需在Linux终端中键入它)虽然非常基本但应该给出错误处理的一些想法:
在第二行之后没有任何内容打印到终端,因为“foo”使得grep返回1并且我们检查grep的返回码是否等于0.第二个条件语句在最后一行回显它的消息,因为它是真的由于CHECK == 1 .
正如您所看到的那样,如果您正在调用此过程,那么有时必须查看它返回的内容(通过main()的返回值) .
我相信
main()
应该返回EXIT_SUCCESS
或EXIT_FAILURE
. 它们在stdlib.h
中定义在C中,main函数应声明为int main()而不是void main(),因为编译器会在void main的情况下抛出错误 . main函数可以使用任意数量的参数,如int main(int k,int l,int arr [])或int main(void) .
输出:
来到返回部分它应该只返回0否则编译器会抛出错误 . 例如,如果返回1,您将获得所需的输出,但它也会引发运行时错误 .
例
输出: