I'm working on a C-brain teaser: Write the standard Hello-World program, without semi-colons.
My best answer so far is:
int main(void)
{
if (printf("Hello World!\n"), exit(0), 0)
{
/* do nothing */
}
}
But I don't understand why I don't get compiler error (Visual Studio):
error C4716: 'main' : must return a value
I've tried other functions with a return-type declared, but missing a return-statement, and get this compiler error.
Note that I've also tried:
int foo(void)
{
if (printf("Hello World!\n"), exit(0), true)
{
/* do nothing */
}
}
int main(void)
{
foo();
}
And don't get a compiler error on foo. If I remove the "exit(0)", I do get the compiler error. Apparently the compiler has knowledge that "exit" is a special function? This seems very odd to me.
In a main function, the return statement and expression are optional. What happens to the returned value, if one is specified, depends on the implementation.
In C++ language, the main() function can be left without return value.
The answer is yes. We can write program, that has no main() function. In many places, we have seen that the main() is the entry point of a program execution. Just from the programmers perspective this is true.
As Jens pointed out in a comment, the posted code does not exhibit undefined behavior. The original answer here isn't correct and doesn't even really seem to answer the question anyway (on re-reading everything a few years later).
The question can be summed up as, "why doesn't MSVC issue warning C4716 for main()
in the same circumstances it would for other functions"?
Note that diagnostic C4716 is a warning, not an error. As far as the C language is concerned (from a standards point of view anyway), there's never a requirement to diagnose a non-error. but that doesn't really explain why there's a difference, it's just a technicality that may mean you can't complain too much...
The real explanation for why MSVC doesn't issue the warning for main()
when it does for other functions can really only be answered by someone on the MSVC team. As far as I can tell, the docs do not explain the difference, but maybe I missed something; so all I can do is speculate:
In C++, the main()
function is treated specially in that there's an implicit return 0;
just before the closing brace.
I suspect that Microsoft's C compiler provides the same treatment when it's compiling in C mode (if you look at the assembly code, the EAX register is cleared even if there's no return 0;
), therefore as far as the compiler is concerned there is no reason to issue warning C4716. Note that Microsoft's C mode is C90 compliant, not C99 compliant. In C90 'running off the end' of main()
has undefined behavior. However, always returning 0 meets the low requirements of undefined behavior, so there's no problem.
So even if the program in the question did run off the end main()
(resulting in undefined behavior) there still wouldn't be a warning.
Original, not so good answer:
In ANSI/ISO 90 C, this is undefined behavior, so MS really should produce an error (but they aren't required to by the standard). In C99 the standard permits an implied return
at the end of main() - as does C++.
So if this is compiled as C++ or C99, there's no error and it's the same as return 0;
. C90 results in undefined behavior (which does not require a diagnostic).
Interestingly (well, maybe not), of the several compilers (VC9, VC6, GCC 3.4.5, Digital Mars, Comeau) I tried this on with my basic, mostly default options set (the environment I pretty much always use for quick-n-dirty testing of code snippets) the only compiler that warns about the missing return statement is VC6 when compiling as a C++ program (VC6 does not complain when compiling for C).
Most of the compilers complain (a warning or error) if the function is not named main
. Digital Mars when compiling for C does not and GCC doesn't for C or C++.
if you don't return anything the program will return 0. See http://www.research.att.com/~bs/bs_faq2.html#void-main
The compile may be smart enough to know that exit(0) is being called, which never returns so it's not needed.
C++ Language Reference
exit Function
The exit function, declared in the standard include file STDLIB.H, terminates a C++ program.
The value supplied as an argument to exit is returned to the operating system as the program's return code or exit code. By convention, a return code of zero means that the program completed successfully.
Note You can use the constants EXIT_FAILURE and EXIT_SUCCESS, defined in STDLIB.H, to indicate success or failure of your program.
Issuing a return statement from the main function is equivalent to calling the exit function with the return value as its argument.
Because it's not an error -- it's undefined behavior. See section 6.9.1, paragraph 12 of the C99 standard:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
Thus, the compiler is free to do whatever it wants when seeing your code failing to return -- it can emit an error, a warning, or nothing at all. In the case of GCC, it by default compiles successfully with no warnings or errors. With the -Wall
option, it emits a warning.
main()
is special in C: it's the only function that's allowed not to return a value. The C standard says that if control reaches the end of main()
without a return
statement, it implicitly returns 0. This is only true for main()
, all other non-void functions must return a value.
Section 5.1.2.2.3:
If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument;10) reaching the } that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.
Not returning from main, or more precisely, not reaching the terminating '}' of the main function is perfectly fine for a variety of reasons. Typical cases include looping forever and exiting or aborting before.
In this case, the exit(0)
is guaranteed to be executed before the end of main is reached. Why should the compiler warn? You wouldn't expect a warning for these, would you?
int main (void) { for (;;) { /* do something useful */ } }
int main (void) { /* do something */; exit (0); }
I'd even be surprised if
int main (void)
{
if (printf("Hello World!\n"), exit(0), true)
{
/* do nothing */
}
return 0;
}
wouldn't cause warning: unreachable code: return 0
or somesuch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With