Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no compiler error for main() without a return at the end?

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.

like image 381
abelenky Avatar asked Jan 29 '09 21:01

abelenky


People also ask

Does main need a return statement?

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.

Does main need a return statement C++?

In C++ language, the main() function can be left without return value.

Can a code be compiled without main () function?

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.


6 Answers

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++.

like image 64
Michael Burr Avatar answered Oct 03 '22 12:10

Michael Burr


if you don't return anything the program will return 0. See http://www.research.att.com/~bs/bs_faq2.html#void-main

like image 26
ggf31416 Avatar answered Oct 03 '22 14:10

ggf31416


The compile may be smart enough to know that exit(0) is being called, which never returns so it's not needed.

like image 23
John Boker Avatar answered Oct 03 '22 13:10

John Boker


From http://msdn.microsoft.com/en-us/library/k9dcesdd(VS.71).aspx

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.


like image 38
John MacIntyre Avatar answered Oct 03 '22 14:10

John MacIntyre


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.

like image 20
Adam Rosenfield Avatar answered Oct 03 '22 12:10

Adam Rosenfield


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.

like image 21
Jens Avatar answered Oct 03 '22 13:10

Jens