void main与int main之间的区别是什么?”这是一个常见的问题。我们来探讨一下这个问题,并深入研究一些有关main()函数不同版本的更多的东西。          C与C++在main()函数方面的标准有所不同,所以我们要分开讨论。 对于C语言:          在C89标准中,main() 的形式是可以接受的,当然使用如下的C99标准更明智,因为在这个标准中只有如下格式才能被接受:          int main ( void )          int main ( int argc, char *argv[] )          我们可以对main函数做轻微的改变,比如我们可以用一个自定义的类型代替int(当然这个类型必须被定义为int型),还可以把*argv[]改为**argv,等等。          如果我们不想在命令行下对程序输入参数,可以选择第一种形式。          其实第二种形式的两个参数argc,argv的名称是可以改变的,但保持原样是更明智的选择。          main()函数的返回类型必须为int;返回的整形值作为传递给调用者的一个返回码。(this allows a return code to be passed to the invoker)          对于C++:          以下是可以接受的格式:          int main ( int argc, char *argv[] )          int main ()          第一种格式遵从C99标准;第二种格式在不需要通过命令行向程序传递参数时使用,与C99标准中规定的格式int main(void)效果相同。          (C)int main()与int main(void)之间的区别:          很多C程序员都曾搞错的一个概念,就是以为这样一个函数不接受任何参数:          int foo();          事实上,这个函数被认为可以接受未知个数的参数(译:可接受任意多的参数!)。正确的用法是
在括号内添加关键字void。          void main()函数是如何处理的?          在C/C++正规的调用/返回函数中,如果你不想让一个函数返回任何值,你可以使用void定义返回类型。比如,一个不接受任何参数并且无任何返回值的函数原型可以像这样:          void foo(void);          一个常见的误解是,这种逻辑同样适用于main()函数。呵呵,事实并非如此,main()函数是很特殊的,无论何时你都应该依照标准定义main()函数(译:即使用int main()的形式!),并把返回值定义为int。有时void main()的例外形式是可以出现的,但这仅限于某些特定的系统。如果你不敢肯定正在使用这些系统,那么答案很简单,不能使用void main()的形式。          如果你在论坛上写了像“void main”这样的代码而被警告,那么最好改过来。不要用"我的老师告诉我这么做是对的"之类的话来为自己开脱;老师们总是习惯犯错误(teachers have a bad habit of being wrong)。写安全的,合乎标准的代码,大家就可以专注于你程序中其它的问题而不是在这种规范方面的东西上浪费时间。      但是int main(int argc, char *argv[], char *envp[])又是怎么回事呢?          好比是标准的扩展版,main()函数可以在一些系统中提取一个额外的参数用来访问环境变量。这个用法不能保证在每个编译环境中都行得通,所以使用 envp 这个参数是还是谨慎为妙。          最后,关于为什么void main(void)是一种错误的用法,这个链接提供了一些更细节化的背景资料:          users.aber.ac.uk/auj/voidmain.s
html          总之,尽量用int main()这个更标准,程序也会更安全。
void main(void) - the Wrong Thing
The newsgroup, comp.lang.c, is plagued by an almost continuous discussion of whether we can or cannot use void as a return type for main. The ANSI standard says "no", which should be an end of it. However, a number of beginners' books on C have used void main(void) in all of their examples, leading to a huge number of people who don't know any better.
When people ask why using a void is wrong, (since it seems to work), the answer is usually one of the following:
Because the standard says so.()c语言是啥
(To which the answer is usually of the form "but it works for me!")
Because the startup routines that call main could be assuming that the return value will be
pushed onto the stack. If main() does not do this, then this could lead to stack corruption in the program's exit sequence, and cause it to crash.
(To which the answer is usually of the form "but it works for me!")
Because you are likely to return a random value to the invokation environment. This is bad, because if someone wants to check whether your program failed, or to call your program from a makefile, then they won't be able to guarantee that a non-zero return code implies failure.
(To which the answer is usually of the form "that's their problem").
This page demonstrates a system on which a void main(void) program will very likely cause problems in the third class above. Calling the program from a script may cause the script to die, whether or not its return code is checked. Calling it from a makefile may cause make to complain. Calling it from the command line may cause an error to be reported.
RISC OS is the native operating system of Acorn's range of ARM based computers. One of
the facilities of this OS is a system variable, Sys$RCLimit. The value of this variable specifies the maximum value that a program may return to the OS without causing RISC OS itself to raise an error. The default value of this variable is set by the OS at 256. I'm not too sure what the intended function of this variable was, but it exists, and that's that.
Now, let's look at an example program using int main(void).
int main(void)
{
    return 42;
}
Compiling it to ARM assembly language, using gcc (as an aside: Acorn's own C compiler reports a warning with void main(void) and converts it to an integer function returning zero) gives the following:
|main|:
        mov    ip, sp 
        stmfd  sp!, {rfp, fp, ip, lr, pc}
        sub    fp, ip, #4
        cmps    sp,sl
        bllt    |x$stack_overflow|
        bl      |___main|
        mov    r0, #42
        ldmdb  fp, {rfp, fp, sp, pc}^
The first six instructions are initialisation and stack checking. The final two return 42 to the library startup code. So, the return value of main is passed in R0. Note that the library start
up code is expecting to call a function returning an integer, so will happily use the value returned in R0.
What happens with a void main function? Well, here's an example.
#include <stdio.h>
char buf[1024];
void main(void)
{
    (void)fgets(buf, 1024, stdin);
}
The program waits for a line of text from its standard input, nothing else. Again we compile it to assembler:
|.LC0|:
        dcd    |__iob|
|.LC1|:
        dcd    |buf|
|main|:
        mov    ip, sp 
        stmfd  sp!, {rfp, fp, ip, lr, pc}
        sub    fp, ip, #4
        cmps    sp,sl
        bllt    |x$stack_overflow|
        bl      |___main|
        ldr    r2, [pc, #|.LC0| - . - 8]
        mov    r1, #1024
        ldr    r0, [pc, #|.LC1| - . - 8]
        bl      |fgets|
        ldmdb  fp, {rfp, fp, sp, pc}^
        area    |buf|, DATA, COMMON, NOINIT
        %      1024
Again, the first six instructions in main set things up. The next three set up the arguments for the call to fgets. Then we call fgets and return to the caller. stdio.h says that fgets returns a pointer to the buffer. So, in this instance, what we are returning to the library startup code is a pointer to buf. Under RISC OS, all C programs are mapped into memory at 0x8000. So, we will be returning a value to the OS which is > 32768 (hence, certainly > t
he default value of Sys$RCLimit). The OS then raises an error.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。