我常常在论坛周围看到臭名昭着的void main()
,并且在问题告诉用户永远不会使用void main()
(我完全同意)之后几乎立即发表评论。但是void main()
的起源在哪里?
为什么我仍然看到较新的人习惯于在正确的方式返回main
时int
没有返回任何内容。
我理解为什么这种方法是错误的,如this问题和其他许多人所解释的那样,但我不知道这种声明main
的方法是怎么产生的,甚至不是为什么它仍然教给一些学生。
答案 0 :(得分:10)
即使Bjarne Stroustrup用C ++编写了void main
,所以它确实是一种常见的反模因,也是一种旧模式,早于支持void main
的Java和其他当代语言。当然Bjarne还写道void main
从未成为C或C ++的一部分。然而,对于后一种说法(在他的常见问题解答中),至少从C99开始,看起来Bjarne是错的,因为C99标准的N869草案在其§5.1.2.2.3/ 1中表示
“如果
main
函数的返回类型是与int
兼容的类型,则从初始调用到main
函数的返回等同于调用exit
使用main
函数返回的值作为其参数的函数;到达终止}
函数的main
返回值0.如果返回类型与int
不兼容,则返回到主机环境的终止状态未指定。“ p>
早些时候,在其§5.1.2.2.1/ 1中,它陈述了main
的签名,
“或其他一些实现定义的方式。”
返回类型“与int
不兼容”可以是void
。
所以,虽然这不是一个完整的答案(我怀疑网上有关于此的历史资料),但至少它在某种程度上纠正了问题的假设。事实并非void main
在C和C ++中是完全可憎的。但是在C ++中它是无效的:它是托管C ++实现中不支持的C事物。
答案 1 :(得分:4)
我一直是这个问题的受害者,所以我想我可以告诉你为什么会这样,在我们的C讲座中,院系必须使用示例程序(可能是“Hello World”)开始我们的讲座,为此他们有使用 main()方法。
但是既然他们不想让学生感到困惑,而且他们也不想在C编程课程的最开始就进入教学返回类型和返回语句的复杂性,他们会使用(并且还要求我们使用) void main()并告诉我们假设这是默认类型,直到我们详细研究函数和返回类型。
因此,这导致了在我们的C-Programming的第一堂课中使用void main()的错误习惯。
希望能够很好地解释为什么大多数计算机程序员尤其是新手计算机程序员都会采用这种不良做法。
干杯, Mayank
答案 2 :(得分:2)
我个人认为如下:K& RC不需要指定返回类型,并且隐含地假设它是int 和同时K& R 中的示例没有使用返回值。
例如,K& R第一版中的第一个代码如下:
#include <stdio.h>
main()
{
printf("Hello World\n");
}
所以难怪后来读这篇文章(在一些编译器将一个void类型作为扩展添加到语言之后)假设main实际上有一个void return语句。我会做同样的事情。< / p>
实际上K&amp; R稍后会说:
为简单起见,我们省略了返回语句 到目前为止我们的主要功能,但我们将包括它们 此后,提醒一下程序应该将状态返回给他们 环境。
所以这只是另一个例子,当你编写错误的代码时会发生什么,并且假设人们在做愚蠢的事情之前会读取所有内容,然后包含免责声明;)
答案 3 :(得分:2)
作为众多其他作者中的一位作者,赫伯特·希尔特(Herbert Schildt)写了一些受欢迎但不一定高质量的书籍,这些书籍支持这一想法。
一个令人震惊的例子是他的The Annotated C Standard。他在左侧页面上引用了ISO / IEC 9899:1990标准,并在右侧页面上提供了注释。当他引用第5.1.2.2.1节“程序启动”时,它说:
程序启动时调用的函数名为
main
。该实现声明此函数没有原型。它可以不带参数定义:int main(void) { /* ... */ }
或带有两个参数(...):
int main(int argc, char *argv[]) { /* ... */ }
这不包括添加到C99的'或其他一些实现定义的方式'。
然后,在注释中,他说:
有趣的是,编译器声明的
main()
没有原型。因此,您可以根据程序的要求自由声明main()
。例如,以下是声明main()
的三种常用方法:void main(void) /* no return value, no parameters */ int main(void) /* return a value, no parameters */ /* return a value and include command-line parameters */ int main(int argc, char *argv[])
C90标准不允许第一个版本,尽管他说,但无辜的读者可能会感到困惑。
请注意,第5.1.2.2.3节程序终止说:
从初始调用到
main
函数的返回等同于调用exit
函数,其中main
函数返回的值作为其参数。如果main
函数执行不指定值的返回,则返回到托管环境的终止状态是未定义的。
由于您发现exit
采用int
参数,因此很明显main
的返回类型应为int
。
评论说:
在大多数实现中,
main()
的返回值(如果有)将返回给操作系统。请记住,如果您没有从main()
显式返回值,那么传递给操作系统的值在技术上是未定义的。虽然大多数编译器在没有指定其他返回值时会自动返回0(即使main()
被声明为void
),但您不应该依赖这个事实,因为标准不能保证这一点。
这篇评论中的一些是如此多的牛排泄物,这种观点我并不孤单。本书中唯一的优点是它几乎包含了所有C90标准(fprintf
的描述中缺少一页 - 同一页面被打印两次)远远低于标准的成本。有人认为,价格差异代表了评论的价值损失。有关C的一些信息以及带注释的C标准的Lysator,请参见Clive Feather's review。
他的另一本书是C: The Complete Reference,至少达到了第4版。 3rd Edition广泛使用void main()
;这可能已经被第4版清理过了,但令人遗憾的是,许多版本都需要这样一个基本问题才能正确。
答案 4 :(得分:1)
可能的原因:
public static void main(...)
。main
不会返回,尽管它会隐式返回0
。main()
,默认情况下它是int
。也许有些人认为缺少的返回类型相当于void
。答案 5 :(得分:1)
从C ++的角度来看,存在3个混乱的来源:
int main()
,而不是真正了解标准本身的完整情况。 C和C ++对于独立系统中应该如何声明main()(在编写裸机嵌入式系统或操作系统时)有完全不同的规则。我将在这个答案中解决每一个混乱的来源。
PC /桌面程序员是有问题的,因为他们认为托管系统是唯一存在的系统,因此传播关于正确形式的main()的不正确/不完整的宣传,教条地说明你必须使用int main()
,不正确在这样做时引用标准,如果有的话。
C和C ++标准总是列出两种系统:独立系统和托管系统。
在独立实现中,C中一直允许使用void main (void)
。在C ++中,独立实现略有不同:独立实现可能不会将入口函数命名为main(),或者它必须遵循返回的声明表单int
。
Bjarne Stroustrup甚至没有设法cite the standards or explain this correctly/completely,所以难怪普通程序员感到困惑! (他引用了托管环境子章节,并没有引用它的所有相关部分。)
这是all discussed in detail with references to the standard(s) here,Bjarne和其他人请阅读。
关于托管系统中的void main (void)
,这可以从ISO C标准之前的黑暗时代的某个地方开始,在那里允许一切。
我怀疑它背后的主要罪魁祸首是Borland Turbo C编译器,它在1990年ISO C发布时已经是市场领导者。这个编译器允许void main (void)
。
应该注意的是,在托管系统的C90中隐式禁止托管实现的void main (void)
,不允许实现定义的表单。所以Turbo C从来都不是一个严格符合要求的实现。然而,仍然在学校(特别是在印度)使用!从头开始教授每个学生不正确的编程标准。
自C99以来,{C}允许void main (void)
和其他形式,因为添加了一个奇怪的句子:&#34;或者以其他一些实现定义的方式&#34;。这也在上面的链接答案中讨论,参考C99基本原理和C标准的其他部分,假设托管系统main()可能不返回int。
因此,在C中,void main (void)
(可以说)当前是托管实现的允许形式,因为编译器会记录它的作用。但请注意,由于这是实现定义的行为,是编译器确定是否允许此表单,而不是程序员!
在C ++中,void main (void)
不是允许的形式。
答案 6 :(得分:1)
在没有操作系统的裸机上运行的嵌入式程序永远不会返回。上电时,复位向量间接跳转到main
,在main
内,有一个无限while (1){}
个循环。从语义上讲,main
的返回值没有意义。