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:
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)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:
{
return 42;
}
|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}^
What happens with a void main function? Well, here's an example.
#include <stdio.h>The program waits for a line of text from its standard input, nothing else. Again we compile it to assembler:
char buf[1024];
void main(void)
{
(void)fgets(buf, 1024, stdin);
}
|.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
Here's the result of compiling and running the program:
SCSI: void % gcc void.c -o void
Drlink AOF Linker Version 0.28 30/07/95
SCSI: void % show Sys$RCLimit
Sys$RCLimit : 256
SCSI: void % void
I enter this line
Return code too large
SCSI: void %
And, in a script file:
SCSI: void % cat script
void
echo Finished
SCSI: void % run script
I enter this line
Return code too large
SCSI: void %
Note that the example above was a little contrived in order to make the final function call return a pointer. A better example where this could cause problems is one where the program uses printf to report a usage string > 256 characters long prior to returning or, worse still, one where the program uses printf to output data depending on user input. Depending on the length of the user's input text, the program may or may not cause an error which is solely due to the use of void as a return type for main.
So, if you want your software to be portable, please make main return int. It does matter.
The information provided on this and other pages by me, Alun Jones is under my own personal responsibility and not that of Aberystwyth University. Similarly, any opinions expressed are my own and are in no way to be taken as those of the University.
My GPG public key is here This page is located at: http://users.aber.ac.uk/auj/voidmain.shtml It was last modified on Tue Apr 10 13:34:04 2001 It has been accessed 77170 times since 5 Jul 2000 |
文章评论(0条评论)
登录后参与讨论