void main()的写法来源于main()的写法的二义性和return的可选性。
由于C语言被设计为汇编语言的简单抽象,而int返回值一般是保存在算术寄存器如AX中传递,设置和接收返回值只需一条MOV指令,因此早期C语言没有void,函数不写返回类型就是int类型,不写return就是没有返回值,函数调用语法被设计为返回值可以被轻松忽略。
所以早期main函数的写法是main(),但是这样的写法,返回值到底有没有这个问题,容易搞不清楚,实际上K&R的《C Programming Language》(1978/1988)就很多地方main()没有写return,这也影响了一些编译器,比如Lattice C就会直接忽略main()的返回值。
后来为了解决这个问题,有的编译器添加了void,main()的写法就分化为了void main()和int main(),很多人并没有注意到main()有返回值,因为很多教程main里边就是没有return的,因此接受void main()的人更多。这也影响到了一些官方的教程,比如Turbo C 2.0的参考指南等早期教程就是void main()居多。
后来有人意识到了这个问题,大力推广int main()的写法,不鼓励main()和void main()的写法,这个问题才得到一定的解决。C++更是直接废除了main()和void main()的写法。
不过还是有人忘记写return,因为main函数返回值的作用有限,而return这个关键字打字太多,因此C99开始规定如果int main()不写return自动返回0。
--------
Lattice C 3.0的C.ASM调用_main函数代码片段:
;
; set up args for _main and call it
;
M9: MOV _SP,SP ; save stack pointer reset value
PUSH DS ; make ES same as DS
POP ES
CALL _MAIN ; call C main
IF MSDOS EQ 1
CMP _DOS,2
JL M91 ; branch if DOS 1
ENDIF
MOV AX,4C00H ; exit with return code of 0
INT 21H
IF MSDOS EQ 1
M91: MOV SP,BP ;restore ptr to far return
RET ;return to MS-DOS
ENDIF
_MAIN.C中_main函数调用main函数代码片段:
/*
*
* Call user's main program
*
*/
main(_ARGC,_ARGV,environ); /* call main function */
#ifndef TINY
exit(0);
#else
_exit(0);
#endif
Turbo C 2.0参考指南中的void main(实际上Turbo C 1.0已经支持int main):