true

What is the correct (most efficient) way to define the main() function in C and C++ — int main() or void main() — and why? If int main() then return 1 or return 0?


There are numerous duplicates of this question, including:

Related:

22 upvote
  flag
I still think it's fairly vague too. Define "most efficient" for me. Efficient in what sense? In the sense of taking up less memory? In the sense of running faster? I can see the useful answers but I still think the question is phrased pretty poorly. – Onorio Catenacci
6 upvote
  flag
Pish posh, the context of efficient is obvious here, especially with the examples (which are likely there to clarify the definition of 'efficient'). Hopefully the poor buffer didn't crawl into a hole and regret the question entirely. One could say, regardless of void or int, a value is returned, so it has no impact on file size, operations executed, nor memory allocated. And people, across most OSs, tend to return 0 on success, and something else on -other- success, or failure - but there is no standard. Ultimately, no difference in efficiency in any obvious way. – Kit10
upvote
  flag
"correct (most efficient)" doesn't make sense. Efficient is one thing, correct is another. main is called once (and in C++ can only be called once: no recursion). If you don't want execution to spend a lot of time in main, then don't invoke the program a large number of times: make the program implement the repetition. – Kaz
1 upvote
  flag
I find it interesting that none of the answers, as far as I can tell, provide a fully working example, including the #include statements – puk
upvote
  flag
@puk: there's no need for 'fully working example', and no headers are needed to write main() -- even though it would be an unusual program that did not need some headers. – Jonathan Leffler
upvote
  flag
What every answer here so far fails to mention is that the chapter about main's return type, quoted all over, is a sub-chapter of the hosted environment chapter, which is turn is a sub-chapter of the relevant chapter Execution environments. Present answers at this moment only cover 50% of the standard. So I wrote an answer which aims to answer the question to 100%. – Lundin
upvote
  flag
upvote
  flag
This questin may be extends with What is the Standard, and recommend way of using main() in C programs. – EsmaeelE

19 Answers 11

up vote 430 down vote accepted

The return value for main should indicate how the program exited. Normal exit is generally represented by a 0 return value from main. Abnormal termination is usually signalled by a non-zero return but there is no standard for how non-zero codes are interpreted. Also as noted by others, void main() is explicitly prohibited by the C++ standard and shouldn't be used. The valid C++ main signatures are:

int main()

and

int main(int argc, char* argv[])

which is equivalent to

int main(int argc, char** argv)

It's also worth noting that in C++, int main() can be left without a return value at which point it defaults to returning 0. This is also true with a C99 program. Whether return 0 should be omitted or not is open to debate. The range of valid C program main signatures is much greater.

Also, efficiency is not an issue with the main function. It can only be entered and left once (marking program start and termination) according to the C++ standard. For C, the case is different and re-entering main() is allowed, but should probably be avoided.

46 upvote
  flag
main CAN be entered/left multiple times, but that program probably wouldn't win any design awards ;) – korona
7 upvote
  flag
C99 also has the C++ mis-feature that reaching the end of the main() function is equivalent to returning 0 -- if main() is defined to return a type compatible with int (section 5.1.2.2.3). – Jonathan Leffler
53 upvote
  flag
reentering main is not valid C++. Explicitly in the standard, 3.6.1.3 states 'main shall not be used within a program' – workmad3
97 upvote
  flag
stdlib.h provides EXIT_SUCCESS and EXIT_FAILURE for this purpose – Clay
upvote
  flag
@korona: using main() from inside the code is undefined behavior. As the compiler may(depending on compiler) insert code to handle program initialization at this point. Running the initialization code twice may not be a good idea. – Martin York
15 upvote
  flag
0 and non-zero are correct but entirely meaningless to someone reading your code. This question is proof that people don't know what valid/invalid codes are. EXIT_SUCCESS/EXIT_FAILURE are much more clear. – JaredPar
1 upvote
  flag
JaredPar: returning 0 from main is clearly defined in C as a successful termination. Martin York: calling main() from inside a C program is certainly not undefined behavior. I cannot say the same for C++. – Chris
upvote
  flag
As said, for C++ calling main() is explicitly stated in the standard as illegal (which is a step worse than undefined). For C though, the case is obviously different (but probably best avoided ;)) – workmad3
upvote
  flag
It may be clearly defined in the C standard but it's definately not clearly common knowledge. Otherwise this question wouldn't have been posted. – JaredPar
6 upvote
  flag
JaredPar: well, it's common knowledge among programmers that know C, and usually I'd expect people reading C source to understand C. – Chris
3 upvote
  flag
@workmad3, notice this defect report though about using main for GCC: gcc.gnu.org/bugzilla/show_bug.cgi?id=41431 . Also notice the following for allowed definitions of main: groups.google.com/group/comp.std.c++/browse_thread/thread/… – Johannes Schaub - litb
upvote
  flag
Is it guaranteed the return value of the main function will be the exit code of the program? I always used the exit function in my programs to set the exit code other than 0. – Calmarius
1 upvote
  flag
@Calmarius: Yes. Section 5.1.2.2.3 of the standard says "...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..." – Nemo
3 upvote
  flag
Every C developer knows INT exit code 0 means success, so why so much drowning in a glass of water? – Frank R.
upvote
  flag
This answer only covers 50% of the standards as it doesn't mention freestanding implementations. "void main() is explicitly prohibited by the C++ standard"... quotation needed (you won't find one, it rather implicitly prohibits void main() for hosted systems). – Lundin
upvote
  flag
@Lundin main() is only talked about for the hosted forms of C and C++. So the question is implicitly about hosted C and C++. – Veltas
upvote
  flag
Technically, the signature should be unsigned char main(...), because the vast majority of shell environments require you to return a value between 0 and 255. – Majora320
1 upvote
  flag
@Majora320: not really. The standards say int and mean int. However, you're correct that only the least significant 8 bits of the int are used as exit status. See also Exit codes bigger than 255 — possible?. – Jonathan Leffler

Return 0 on success and non-zero for error. This is the standard used by UNIX and DOS scripting to find out what happened with your program.

This basically depends on your execution environment (the OS). C implies that it will be run by a UNIX like OS which expects the program to return a (small? 1 Byte? can't remember) integer to indicate success / failure.

You should probably just use int main(int argc, char** argv).

1 upvote
  flag
See Exit codes bigger than 255 — possible? Yes, only values from 0 to 255 can be returned. – Jonathan Leffler

I believe that main() should return either EXIT_SUCCESS or EXIT_FAILURE. They are defined in stdlib.h

1 upvote
  flag
17 upvote
  flag
0 is also standard. – Chris
2 upvote
  flag
@ChrisYoung There is EXIT_SUCCESS and EXIT_FAILURE because some historic operating systems (VMS?) used a different number than 0 to denote success. It's 0 everywhere nowadays. – fuz
3 upvote
  flag
@FUZxxl you're correct, but that's not in conflict with my comment. EXIT_SUCCESS can indeed be nonzero, but the standards (C89, C99, C11) all define 0 (as well as EXIT_SUCCESS) to also be an implementation-defined form of the status successful termination. – Chris
upvote
  flag
@ChrisYoung Thank you for correcting me. I was apparently wrong. – fuz
upvote
  flag
While this comment is correct and valuable, it does not answer the question. – Lundin
1 upvote
  flag
@FUZxxl: It's true the VMS used odd values (like 1) to indicate success and even values (like 0) to indicate failure. Unfortunately, the original ANSI C standard was interpreted to mean that EXIT_SUCCESS had to be 0, so returning EXIT_SUCCESS from main got exactly the wrong behavior on VMS. The portable thing to do for VMS was to use exit(EXIT_SUCCESS), which always did the right thing. – Adrian McCarthy
upvote
  flag
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;11) reaching the } that terminates the main function returns a value of 0." – Lundin
upvote
  flag
And then 7.22.4.4. about the exit function: "If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined." – Lundin

I was under the impression that standard specifies that main doesn't need a return value as a successful return was OS based (zero in one could be either a success or a failure in another), therefore the absence of return was a cue for the compiler to insert the successful return itself.

However I usually return 0.

upvote
  flag
C99 (and C++98) allow you to omit the return statement from main; C89 does not allow you to omit the return statement. – Jonathan Leffler
upvote
  flag
This is a comment not an answer. – Lundin
upvote
  flag
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Steve Lillis
4 upvote
  flag
@SteveLillis: In 2008 SO didn't have a comment section. – graham.reeds

Keep in mind that,even though you're returning an int, some OSes (Windows) truncate the returned value to a single byte (0-255).

4 upvote
  flag
Unix does the same, as do most other operating systems probably. I know VMS does such incredible weird things with it that returning anything other than EXIT_SUCCESS or EXIT_FAILURE is asking for trouble. – Leon Timmermans
1 upvote
  flag
MSDN begs to differ: when reported through mscorlib, an exit code is a signed 32-bit integer. This seems to imply that the C runtime libraries that truncate exit codes are defective. – user824425
upvote
  flag
Yes, this is incorrect. On Windows a 32-bit integer is returned (and converted to unsigned). This is the same on UNIX systems with 32-bit integers. But UNIX-style shells on either system will typically only retain an unsigned 8-bit integer. – John McFarlane

The accepted answer appears to be targetted for C++, so I thought I'd add an answer that pertains to C, and this differs in a few ways.

ISO/IEC 9899:1989 (C90):

main() should be declared as either:

int main(void)
int main(int argc, char **argv)

Or equivalent. For example, int main(int argc, char *argv[]) is equivalent to the second one. Further, the int return type can be omitted as it is a default.

If an implementation permits it, main() can be declared in other ways, but this makes the program implementation defined, and no longer strictly conforming.

The standard defines 3 values for returning that are strictly conforming (that is, does not rely on implementation defined behaviour): 0 and EXIT_SUCCESS for a successful termination, and EXIT_FAILURE for an unsuccessful termination. Any other values are non-standard and implementation defined. main() must have an explicit return statement at the end to avoid undefined behaviour.

Finally, there is nothing wrong from a standards point of view with calling main() from a program.

ISO/IEC 9899:1999 (C99):

For C99, everything is the same as above except:

  • The int return type may not be omitted.
  • You may omit the return statement from main(). If you do, and main() finished, there is an implicit return 0.
upvote
  flag
@ Chris Young : Where is the return value going to. And whats the use of the value returned? Can you explain that. or is it just to avoid undefined behaviour. – MELWIN
upvote
  flag
@ MELWIN : Return value is passed to the host environment. Most of the time it would be your OS, which can pass this value to some other running process by request (e.g. system() call). – Ternvein
upvote
  flag
Regarding "The standard defines 3 values for returning... 0, EXIT_SUCCESS, EXIT_FAILURE", is "0, EXIT_SUCCESS, EXIT_FAILURE" actually part of the ISO-C and C++ specs? If yes, where in the specs? – Trevor Boyd Smith
upvote
  flag
C11 §7.22p3 and §7.22.4.4p5. C++11 references the C standard library, but they're briefly mentioned in §18.5p3. – Chris
upvote
  flag
"If an implementation permits it, main can be declared in other ways, but this makes the program implementation defined, and no longer strictly conforming." Quotation needed. – Lundin
1 upvote
  flag
@Lundin I don't think you need a quote to say that someone is allowed to make a compiler that accepts non-standard-conforming programs, or to have a non-stardard-conforming compiler. That's common knowledge and common sense – KABoissonneault
1 upvote
  flag
@KABoissonneault Implementation-defined behavior is a term from the standard, as opposed to completely undocumented behavior. If you implement something that is listed as implementation-defined behavior, you still follow the standard. In this case C89 which was quoted, lists no such implementation-defined behavior, hence the need of quote, to prove that he is not just making things up out of the blue. – Lundin
1 upvote
  flag
@Lundin You're seeing this the wrong way. What we're talking about is not implementation-defined behavior, we're talking about an implementation deviating from the standard if they choose so. It's more like a child disobeying their parents: you don't need a quote from the parents to tell you in what way a child can go against what the parents said. You just know that the moment the child chooses to do so, they're no longer compliant with their parents' guildelines – KABoissonneault
1 upvote
  flag
@KABoissonneault The part I quoted in my comment is definitely about implementation-defined behavior (as opposed to non-standard compiler extensions.) Thus I am talking about implementation-defined behavior. If you are having a monologue about something else, best of luck with that. – Lundin
1 upvote
  flag
@Lundin I guess the wording in the quote is confusing (the part where they say "but this makes the program implementation defined") but I'm pretty sure the person was talking about non-standard behavior (as said in "If an implementation permits it" and "and no longer strictly conforming [to the standard]") as opposed to actual implementation defined behavior. The person should definitely reword their answer, but I still don't think a quote from the standard is necessary on that – KABoissonneault
upvote
  flag
"but this makes the program implementation defined, and no longer strictly conforming." --> Code is still conforming. Certainly less probable with a implementation defined signature. – chux

If you really have issues related to efficiency of returning an integer from a process, you should probably avoid to call that process so many times that this return value becomes an issue.

If you are doing this (call a process so many times), you should find a way to put your logic directly inside the caller, or in a DLL file, without allocate a specific process for each call; the multiple process allocations bring you the relevant efficiency problem in this case.

In detail, if you only want to know if returning 0 is more or less efficient than returning 1, it could depend from the compiler in some cases, but generically, assuming they are read from the same source (local, field, constant, embedded in the code, function result, etc.) it requires exactly the same number of clock cycles.

What to return depends on what you want to do with the executable. For example if you are using your program with a command line shell, then you need to return 0 for a success and a non zero for failure. Then you would be able to use the program in shells with conditional processing depending on the outcome of your code. Also you can assign any nonzero value as per your interpretation, for example for critical errors different program exit points could terminate a program with different exit values , and which is available to the calling shell which can decide what to do by inspecting the value returned. If the code is not intended for use with shells and the returned value does not bother anybody then it might be omitted. I personally use the signature int main (void) { .. return 0; .. }

upvote
  flag
The format of main() is determined by the implementation, meaning compiler. The programmer does not get chose which form to pick, except when a compiler supports several forms. – Lundin
upvote
  flag
@Lundin The return type will be implementation by the implementation. But the value which to be returned is decided by the programmer. C99 Section 5.1.2.2.3 mentions that the return type of main is compatible with int. Therefore returning int will not be a problem. Although other return types are allowed, but in that case the environment variable having the return value will be unspecified. But If a programmer does return 0; then in bash it can be used to make branches. – phoxis

The return value can be used by the operating system to check how the program was closed.

Return value 0 usually means OK in most operating systems (the ones I can think of anyway).

It also can be checked when you call a process yourself, and see if the program exited and finished properly.

It's NOT just a programming convention.

upvote
  flag
There is nothing in the question indicating that an operative system is present. Returning a value doesn't make any sense in a freestanding system. – Lundin

The return value of main() shows how the program exited. If the return value is zero it means that the execution was successful while any non-zero value will represent that something went bad in the execution.

1 upvote
  flag
This is a comment not an answer to the question. – Lundin

main() in C89 and K&R C unspecified return types default to int

return 1? return 0?
  1. If you do not write a return statement in int main() then the closing { will return 0 by default

  2. Return 0 or return 1 will be received by the environment variable of the OS. So if you are not using that environment variable then you should not worry about the return value of main().

See How can I get what my main function has returned?.

$ ./a.out
$ echo $?

This way you can see that it is the environment variable $? which receives the last one byte of return value of main().

So if you are writing any script then you should take care of the return value of main(), otherwise don't.

In Unix and DOS scripting, return 0 on success and non-zero for error are usually returned. This is the standard used by Unix and DOS scripting to find out what happened with your program and controlling the whole flow.

2 upvote
  flag
Strictly speaking, $? is not an environment variable; it is a shell predefined (or built-in) variable. The difference is hard to spot, but if you run env (without any arguments), it prints the environment, and $? won't be shown in the environment. – Jonathan Leffler
1 upvote
  flag
Returning 0 automatically when main "falls of the end" is only in C++ and C99 onwards, not in C90. – Kaz

Returning 0 should tell the programmer that the program has successfully finished the job.

upvote
  flag
Returning 1 from main() normally signals an error occurred; returning 0 signals success. If your programs always fail, then 1 is OK, but it not the best idea. – Jonathan Leffler
1 upvote
  flag
@JonathanLeffler: The meaning of returning 1 from main is implementation-defined. The only language-defined values are 0, EXIT_SUCCESS (often defined as 0), and EXIT_FAILURE. In OpenVMS, return 1; denotes successful termination. – Keith Thompson
upvote
  flag
VMS is not 'normal' — within the meaning of what I said. Isn't it something like 'any odd value is success; even values are failure' on VMS? – Jonathan Leffler

void main() is forbidden after C90. main should return a value. I used to return 0.

1 upvote
  flag
And void main() wasn't allowed before C90 because void was not really part of the C language before the standard. It (void) did appear a little before the standard in a few compilers, but it was one of the features added to the language by C90. – Jonathan Leffler
2 upvote
  flag
void main() is not actually "forbidden". An implementation is permitted to document that it supports void main() (or void main(void)); if it does so, such programs are valid for that implementation. If the current implementation doesn't document that it permits void main(), then a program that uses it has undefined behavior; no diagnostic is required. (Personally, I'd prefer it if it were forbidden; it would avoid the need for questions like these, since such code would never escape into the wild.) – Keith Thompson

Standard C — Hosted Environment

For a hosted environment (that's the normal one), the C11 standard (ISO/IEC 9899:2011) says:

5.1.2.2.1 Program startup

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent;10) or in some other implementation-defined manner.

If they are declared, the parameters to the main function shall obey the following constraints:

  • The value of argc shall be nonnegative.
  • argv[argc] shall be a null pointer.
  • If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase.
  • If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.
  • The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

10) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as char **argv, and so on.

Program termination in C99 or C11

The value returned from main() is transmitted to the 'environment' in an implementation-defined way.

5.1.2.2.3 Program termination

1 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;11) 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.

11) In accordance with 6.2.4, the lifetimes of objects with automatic storage duration declared in main will have ended in the former case, even where they would not have in the latter.

Note that 0 is mandated as 'success'. You can use EXIT_FAILURE and EXIT_SUCCESS from <stdlib.h> if you prefer, but 0 is well established, and so is 1. See also Exit codes greater than 255 — possible?.

In C89 (and hence in Microsoft C), there is no statement about what happens if the main() function returns but does not specify a return value; it therefore leads to undefined behaviour.

7.22.4.4 The exit function

¶5 Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.

Standard C++ — Hosted Environment

The C++11 standard (ISO/IEC 14882:2011) says:

3.6.1 Main function [basic.start.main]

¶1 A program shall contain a global function called main, which is the designated start of the program. [...]

¶2 An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation defined. All implementations shall allow both of the following definitions of main:

int main() { /* ... */ }

and

int main(int argc, char* argv[]) { /* ... */ }

In the latter form argc shall be the number of arguments passed to the program from the environment in which the program is run. If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs) (17.5.2.1.4.2) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or "". The value of argc shall be non-negative. The value of argv[argc] shall be 0. [ Note: It is recommended that any further (optional) parameters be added after argv. —end note ]

¶3 The function main shall not be used within a program. The linkage (3.5) of main is implementation-defined. [...]

¶5 A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the effect is that of executing

return 0;

The C++ standard explicitly says "It [the main function] shall have a return type of type int, but otherwise its type is implementation defined", and requires the same two signatures as the C standard to be supported as options. So a 'void main()' is directly not allowed by the C++ standard, though there's nothing it can do to stop a non-standard implementation allowing alternatives. Note that C++ forbids the user from calling main (but the C standard does not).

There's a paragraph of §18.5 Start and termination in the C++11 standard that is identical to the paragraph from §7.22.4.4 The exit function in the C11 standard (quoted above), apart from a footnote (which simply documents that EXIT_SUCCESS and EXIT_FAILURE are defined in <cstdlib>).

Standard C — Common Extension

Classically, Unix systems support a third variant:

int main(int argc, char **argv, char **envp) { ... }

The third argument is a null-terminated list of pointers to strings, each of which is an environment variable which has a name, an equals sign, and a value (possibly empty). If you do not use this, you can still get at the environment via 'extern char **environ;'. For a long time, that did not have a header that declared it, but the POSIX 2008 standard now requires it to be declared in <unistd.h>.

This is recognized by the C standard as a common extension, documented in Annex J:

J.5.1 Environment arguments

¶1 In a hosted environment, the main function receives a third argument, char *envp[], that points to a null-terminated array of pointers to char, each of which points to a string that provides information about the environment for this execution of the program (5.1.2.2.1).

Microsoft C

The Microsoft VS 2010 compiler is interesting. The web site says:

The declaration syntax for main is

 int main();

or, optionally,

int main(int argc, char *argv[], char *envp[]);

Alternatively, the main and wmain functions can be declared as returning void (no return value). If you declare main or wmain as returning void, you cannot return an exit code to the parent process or operating system by using a return statement. To return an exit code when main or wmain is declared as void, you must use the exit function.

It is not clear to me what happens (what exit code is returned to the parent or OS) when a program with void main() does exit — and the MS web site is silent too.

Interestingly, MS does not prescribe the two-argument version of main() that the C and C++ standards require. It only prescribes a three argument form where the third argument is char **envp, a pointer to a list of environment variables.

The Microsoft page also lists some other alternatives — wmain() which takes wide character strings, and some more.

The Microsoft Visual Studio 2005 version of this page does not list void main() as an alternative. The versions from Microsoft Visual Studio 2008 onwards do.

Standard C — Freestanding Environment

As noted early on, the requirements above apply to hosted environments. If you are working with a freestanding environment (which is the alternative to a hosted environment), then the standard has much less to say. For a freestanding environment, the function called at program startup need not be called main and there are no constraints on its return type. The standard says:

5.1.2 Execution environments

Two execution environments are defined: freestanding and hosted. In both cases, program startup occurs when a designated C function is called by the execution environment. All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified. Program termination returns control to the execution environment.

5.1.2.1 Freestanding environment

In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined. Any library facilities available to a freestanding program, other than the minimal set required by clause 4, are implementation-defined.

The effect of program termination in a freestanding environment is implementation-defined.

The cross-reference to clause 4 Conformance refers to this:

¶5 A strictly conforming program shall use only those features of the language and library specified in this International Standard.3) It shall not produce output dependent on any unspecified, undefined, or implementation-defined behavior, and shall not exceed any minimum implementation limit.

¶6 The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>. A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program.4)

¶7 A conforming program is one that is acceptable to a conforming implementation.5)

3) A strictly conforming program can use conditional features (see 6.10.8.3) provided the use is guarded by an appropriate conditional inclusion preprocessing directive using the related macro. For example:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4) This implies that a conforming implementation reserves no identifiers other than those explicitly reserved in this International Standard.

5) Strictly conforming programs are intended to be maximally portable among conforming implementations. Conforming programs may depend upon non-portable features of a conforming implementation.

It is noticeable that the only header required of a freestanding environment that actually defines any functions is <stdarg.h> (and even those may be — and often are — just macros).

Standard C++ — Freestanding Environment

Just as the C standard recognizes both hosted and freestanding environment, so too does the C++ standard. (Quotes from ISO/IEC 14882:2011.)

1.4 Implementation compliance [intro.compliance]

¶7 Two kinds of implementations are defined: a hosted implementation and a freestanding implementation. For a hosted implementation, this International Standard defines the set of available libraries. A freestanding implementation is one in which execution may take place without the benefit of an operating system, and has an implementation-defined set of libraries that includes certain language-support libraries (17.6.1.3).

¶8 A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

¶9 Each implementation shall include documentation that identifies all conditionally-supported constructs that it does not support and defines all locale-specific characteristics.3

3) This documentation also defines implementation-defined behavior; see 1.9.

17.6.1.3 Freestanding implementations [compliance]

Two kinds of implementations are defined: hosted and freestanding (1.4). For a hosted implementation, this International Standard describes the set of available headers.

A freestanding implementation has an implementation-defined set of headers. This set shall include at least the headers shown in Table 16.

The supplied version of the header <cstdlib> shall declare at least the functions abort, atexit, at_quick_exit, exit, and quick_exit (18.5). The other headers listed in this table shall meet the same requirements as for a hosted implementation.

Table 16 — C++ headers for freestanding implementations

Subclause                           Header(s)
                                    <ciso646>
18.2  Types                         <cstddef>
18.3  Implementation properties     <cfloat> <limits> <climits>
18.4  Integer types                 <cstdint>
18.5  Start and termination         <cstdlib>
18.6  Dynamic memory management     <new>
18.7  Type identification           <typeinfo>
18.8  Exception handling            <exception>
18.9  Initializer lists             <initializer_list>
18.10 Other runtime support         <cstdalign> <cstdarg> <cstdbool>
20.9  Type traits                   <type_traits>
29    Atomics                       <atomic>

What about using int main() in C?

The standard §5.1.2.2.1 of the C11 standard shows the preferred notation — int main(void) — but there are also two examples in the standard which show int main(): §6.5.3.4 ¶8 and §6.7.6.3 ¶20. Now, it is important to note that examples are not 'normative'; they are only illustrative. If there are bugs in the examples, they do not directly affect the main text of the standard. That said, they are strongly indicative of expected behaviour, so if the standard includes int main() in an example, it suggests that int main() is not forbidden, even if it is not the preferred notation.

6.5.3.4 The sizeof and _Alignof operators

¶8 EXAMPLE 3 In this example, the size of a variable length array is computed and returned from a function:

#include <stddef.h>

size_t fsize3(int n)
{
    char b[n+3]; // variable length array
    return sizeof b; // execution time sizeof
}
int main()
{
    size_t size;
    size = fsize3(10); // fsize3 returns 13
    return 0;
}
upvote
  flag
According to §6.7.6.3/14 of the C11 Standard (just above one of the examples you cite), "An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters." This seems to indicate that int main() {} is just fine, as it is a declarator which is part of the function definition. – David Bowling
upvote
  flag
@DavidBowling: A function definition like int main(){ … } does specify that the function takes no arguments, but does not provide a function prototype, AFAICT. For main() that is seldom a problem; it means that if you have recursive calls to main(), the arguments won't be checked. For other functions, it is more of a problem — you really need a prototype in scope when the function is called to ensure that the arguments are correct. – Jonathan Leffler
upvote
  flag
I don't follow. How is int main() { /* function body */ } different from int main(void) { /* function body */ }? I don't think that I have ever seen a function prototype included for main() in a program. A declaration like int func(void); differs from int func(); in that the first specifies no parameters and the second (obsolescent) specifies an arbitrary number of parameters, but I don't see how this applies to the usual int main() {} seen in C programs. – David Bowling
1 upvote
  flag
@DavidBowling: You don't normally call main() recursively, outside of places like IOCCC. I do have a test program that does it — mainly for novelty. If you have int i = 0; int main() { if (i++ < 10) main(i, i * i); return 0; } and compile with GCC and don't include -Wstrict-prototypes, it compiles cleanly under stringent warnings. If it's main(void), it fails to compile. – Jonathan Leffler
upvote
  flag
That is an interesting example, and I see your point now. – David Bowling

Here is a small demonstration of the usage of return codes...

When using the various tools that the Linux terminal provides one can use the return code for example for error handling after the process has been completed. Imagine that the following text file myfile is present:

This is some example in order to check how grep works.

When you execute the grep command a process is created. Once it is through (and didn't break) it returns some code between 0 and 255. For example:

$ grep order myfile

If you do

$ echo $?
$ 0

you will get a 0. Why? Because grep found a match and returned an exit code 0, which is the usual value for exiting with a success. Let's check it out again but with something that is not inside our text file and thus no match will be found:

$ grep foo myfile
$ echo $?
$ 1

Since grep failed to match the token "foo" with the content of our file the return code is 1 (this is the usual case when a failure occurs but as stated above you have plenty of values to choose from).

Now the following bash script (simply type it in a Linux terminal) although very basic should give some idea of error handling:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

After the second line nothing is printed to the terminal since "foo" made grep return 1 and we check if the return code of grep was equal to 0. The second conditional statement echoes its message in the last line since it is true due to CHECK == 1.

As you can see if you are calling this and that process it is sometimes essential to see what it has returned (by the return value of main()).

Note that the C and C++ standards define two kinds of implementations: freestanding and hosted.

  • C90 hosted environment

    Allowed forms 1:

    int main (void)
    int main (int argc, char *argv[])
    
    main (void)
    main (int argc, char *argv[])
    /*... etc, similar forms with implicit int */
    

    Comments:

    The former two are explicitly stated as the allowed forms, the others are implicitly allowed because C90 allowed "implicit int" for return type and function parameters. No other form is allowed.

  • C90 freestanding environment

    Any form or name of main is allowed 2.

  • C99 hosted environment

    Allowed forms 3:

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
    

    Comments:

    C99 removed "implicit int" so main() is no longer valid.

    A strange, ambiguous sentence "or in some other implementation-defined manner" has been introduced. This can either be interpreted as "the parameters to int main() may vary" or as "main can have any implementation-defined form".

    Some compilers have chosen to interpret the standard in the latter way. Arguably, one cannot easily state that they are not strictly conforming by citing the standard in itself, since it is is ambiguous.

    However, to allow completely wild forms of main() was probably(?) not the intention of this new sentence. The C99 rationale (not normative) implies that the sentence refers to additional parameters to int main 4.

    Yet the section for hosted environment program termination then goes on arguing about the case where main does not return int 5. Although that section is not normative for how main should be declared, it definitely implies that main might be declared in a completely implementation-defined way even on hosted systems.

  • C99 freestanding environment

    Any form or name of main is allowed 6.

  • C11 hosted environment

    Allowed forms 7:

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
    
  • C11 freestanding environment

    Any form or name of main is allowed 8.


Note that int main() was never listed as a valid form for any hosted implementation of C in any of the above versions. In C, unlike C++, () and (void) have different meanings. The former is an obsolescent feature which may be removed from the language. See C11 future language directions:

6.11.6 Function declarators

The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.


  • C++03 hosted environment

    Allowed forms 9:

    int main ()
    int main (int argc, char *argv[])
    

    Comments:

    Note the empty parenthesis in the first form. C++ and C are different in this case, because in C++ this means that the function takes no parameters. But in C it means that it may take any parameter.

  • C++03 freestanding environment

    The name of the function called at startup is implementation-defined. If it is named main() it must follow the stated forms 10:

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
    
  • C++11 hosted environment

    Allowed forms 11:

    int main ()
    int main (int argc, char *argv[])
    

    Comments:

    The text of the standard has been changed but it has the same meaning.

  • C++11 freestanding environment

    The name of the function called at startup is implementation-defined. If it is named main() it must follow the stated forms 12:

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
    

References

  1. ANSI X3.159-1989 2.1.2.2 Hosted environment. "Program startup"

    The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

    int main(void) { /* ... */ } 
    

    or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

    int main(int argc, char *argv[]) { /* ... */ }
    
  2. ANSI X3.159-1989 2.1.2.1 Freestanding environment:

    In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.

  3. ISO 9899:1999 5.1.2.2 Hosted environment -> 5.1.2.2.1 Program startup

    The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

    int main(void) { /* ... */ } 
    

    or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

    int main(int argc, char *argv[]) { /* ... */ }
    

    or equivalent;9) or in some other implementation-defined manner.

  4. Rationale for International Standard — Programming Languages — C, Revision 5.10. 5.1.2.2 Hosted environment --> 5.1.2.2.1 Program startup

    The behavior of the arguments to main, and of the interaction of exit, main and atexit (see §7.20.4.2) has been codified to curb some unwanted variety in the representation of argv strings, and in the meaning of values returned by main.

    The specification of argc and argv as arguments to main recognizes extensive prior practice. argv[argc] is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.

    main is the only function that may portably be declared either with zero or two arguments. (The number of other functions’ arguments must match exactly between invocation and definition.) This special case simply recognizes the widespread practice of leaving off the arguments to main when the program does not access the program argument strings. While many implementations support more than two arguments to main, such practice is neither blessed nor forbidden by the Standard; a program that defines main with three arguments is not strictly conforming (see §J.5.1.).

  5. ISO 9899:1999 5.1.2.2 Hosted environment --> 5.1.2.2.3 Program termination

    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;11) 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.

  6. ISO 9899:1999 5.1.2.1 Freestanding environment

    In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.

  7. ISO 9899:2011 5.1.2.2 Hosted environment -> 5.1.2.2.1 Program startup

    This section is identical to the C99 one cited above.

  8. ISO 9899:1999 5.1.2.1 Freestanding environment

    This section is identical to the C99 one cited above.

  9. ISO 14882:2003 3.6.1 Main function

    An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main:

    int main() { /* ... */ }
    

    and

    int main(int argc, char* argv[]) { /* ... */ }
    
  10. ISO 14882:2003 3.6.1 Main function

    It is implementation-defined whether a program in a freestanding environment is required to define a main function.

  11. ISO 14882:2011 3.6.1 Main function

    An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both

    — a function of () returning int and

    — a function of (int, pointer to pointer to char) returning int

    as the type of main (8.3.5).

  12. ISO 14882:2011 3.6.1 Main function

    This section is identical to the C++03 one cited above.

upvote
  flag
One question: Do C++ standards mean that the signature of the startup function in freestanding environments is implementation defined as well? For example, an implementation could have defined the startup function to be: int my_startup_function () or int my_startup_function (int argc, char *argv[]) but can it have, for example: char my_startup_function (long argc, int *argv[]) as a startup function as well? I guess no, right? Also, isn't that ambiguous as well? – Utku
upvote
  flag
@Utku It can have any signature, as long as it isn't named main() because then it must use one the listed signatures. I would imagine the overwhelmingly most common one would be void my_startup_function (), as it doesn't make sense to return from the program on freestanding systems. – Lundin
upvote
  flag
I see. But if it is allowed to use any name and any signature for the startup function, why not allow to use a different signature for main as well? Sorry if that's not a smart question but I couldn't understand the reasoning behind. – Utku
upvote
  flag
@Utku C and C++ are different there. As for why C++ enforces this, I have no idea, there's no rationale. I suspect the main culprit (pun intended) is Stroustrup who early on declared that main must return int, period. Because when he made the first C++ version, he was only used to hosted systems. In the linked post, Stroustrup still seems oblivious about the existence of freestanding implementations: for example, he is ignorantly referring to the hosted implementation sub chapter of the C standard, ignoring the existence of chapter 5.1.2.1. – Lundin
upvote
  flag
Notable thing about C11 standard draft is that even though func() is considered obsolete, the draft itself uses int main() in its own examples. – Antti Haapala

Omit return 0

When a C or C++ program reaches the end of main the compiler will automatically generate code to return 0, so there is no need to put return 0; explicitly at the end of main.

Note: when I make this suggestion, it's almost invariably followed by one of two kinds of comments: "I didn't know that." or "That's bad advice!" My rationale is that it's safe and useful to rely on compiler behavior explicitly supported by the standard. For C, since C99; see ISO/IEC 9899:1999 section 5.1.2.2.3:

[...] 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; reaching the } that terminates the main function returns a value of 0.

For C++, since the first standard in 1998; see ISO/IEC 14882:1998 section 3.6.1:

If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;

All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return; statements at the end of a void function. Reasons against omitting seem to boil down to "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.

So I advocate omitting it; others disagree (often vehemently!) In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.

upvote
  flag
Note: The purpose for this answer is to allow those of us frequently giving this advice on CodeReview a StackOverflow answer to which we can point to regarding the practice of omitting return 0; – Edward
upvote
  flag
This is bad advice because compilers that implement only C89, not any later standard, are still extremely common (I write this in 2017) and will remain extremely common for the foreseeable future. For instance, last I checked no version of Microsoft's compilers implemented C99, and it is my understanding that this is also still typical for embedded-system compilers that aren't GCC. – zwol
1 upvote
  flag
@zwol: Anyone who has no choice but to use a compiler that is out of date by 28 years probably has more problems than deciding whether to explicitly include return 0;, however I would note that many compilers of that era also implemented an implicit return 0; even before it was standardized. – Edward
upvote
  flag
What you say is true. I mean only to give a rationale for the "bad advice" reaction which is not just "it looks weird". – zwol
upvote
  flag
Actually, I do a lot of embedded systems work and haven't encountered a compiler that doesn't support implicit return 0 for over a decade. Also current versions of Microsoft C support it as well. Perhaps your information is out of date? – Edward

What is the correct (most efficient) way to define the main() function in C and C++ — int main() or void main() — and why?

Those words "(most efficient)" don't change the question. Unless you're in a freestanding environment, there is one universally correct way to declare main(), and that's as returning int.

What should main() return in C and C++?

It's not what should main() return, it's what does main() return. main() is, of course, a function that someone else calls. You don't have any control over the code that calls main(). Therefore, you must declare main() with a type-correct signature to match its caller. You simply don't have any choice in the matter. You don't have to ask yourself what's more or less efficient, or what's better or worse style, or anything like that, because the answer is already perfectly well defined, for you, by the C and C+ standards. Just follow them.

If int main() then return 1 or return 0?

0 for success, nonzero for failure. Again, not something you need to (or get to) pick: it's defined by the interface you're supposed to be conforming to.

Not the answer you're looking for? Browse other questions tagged or ask your own question.