70

2 valid versions of main() exist in C++:

int main()  // version 1
int main(int argc, char **argv)  // version 2

But both overloads cannot coexist at the same time. Why not? (Potential use case: while running the program from the terminal, if no arguments are passed the first version is called, otherwise the second version is.)

Does the compiler perform a special check to allow just one version per binary?

James Ko
  • 32,215
  • 30
  • 128
  • 239
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 8
    by reading your question even i am eager to know this – Devjosh Jun 20 '11 at 07:48
  • 8
    Downvoting (it does not make a difference, but just for you to note), for tagging the question with "C" when it is a pure C++ question (i.e. C does not support overloads, the title and first line make it explicit that it is C++). Avoid mixing languages that are not the same in questions around features that are clearly different. – David Rodríguez - dribeas Jun 20 '11 at 08:14
  • 4
    @David, I purposedly put `C` tag because multiple version of `main()` are allowed in `C` also. Moreover, `void main()` is not supported in C++ but mostly it's valid in `C`. However, mentioning `C++` in question, I have cleared by stand. – iammilind Jun 20 '11 at 08:16
  • 10
    `void main()` is not valid C either if you talk about Standard C (C89, C90, C99). – Nawaz Jun 20 '11 at 08:34
  • 3
    "if you pass no argument then 1st version should be called else the 2nd version". The one that is called is the one that the program contains. *If* the program contains the no-arg version, then the command line arguments are ignored. If the program contains the second version and there are no arguments, then `argc` is 1 and `argv` contains a pointer to the program name followed by a null pointer. So even if you could overload it, you wouldn't want that behavior, since even with no arguments there's still an argc/argv pair. – Steve Jessop Jun 20 '11 at 08:47
  • @glglgl, kindly read my comment above, this question is equally applicable to `C` as well. Thanks. – iammilind May 23 '12 at 08:17
  • 1
    @iammilind Yes, but C has no overloading, so two `main()`s can never coexist. And C as well does no signature-dependent mangling. – glglgl May 23 '12 at 08:21

6 Answers6

66

§3.6.1/2 (C++03) says

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() { /* ... */ }
   int main(int argc, char* argv[]) { /* ... */ }

You can use either of them. Both are standard compliant.

Also, since char *argv[] is equivalent to char **argv, replacing char *argv[] with char **argv doesn't make any difference.


But both the versions cannot co-exist at the same time ! (use case can be like: while running the binary from command prompt, if you pass no argument then 1st version should be called else the 2nd version).

No. Both versions cannot co-exist at the same time. One program can have exactly one main function. Which one, depends on your choice. If you want to process command-line argument, then you've to choose the second version, or else first version is enough. Also note that if you use second version, and don't pass any command line argument, then there is no harm in it. It will not cause any error. You just have to interpret argc and argv accordingly, and based on their value, you've to write the logic and the flow of your program.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 5
    Given the question's tagged for 2 languages, it's not clear which Standard you're citing.... – Tony Delroy Jun 20 '11 at 08:07
  • 17
    @Tony: given that the question is actually asking about *overload*s and C does not support overloads, I can only assume that the C tag is misused. Well, that and the fact that the title and first line do make explicit that the discussion of C++. – David Rodríguez - dribeas Jun 20 '11 at 08:11
  • 5
    @Tony: I mentioned it now. Also, `This function shall not be overloaded` makes it clear that its C++. After all, C doesn't support *overloading* of **any** function. – Nawaz Jun 20 '11 at 08:13
  • @David, @Nawaz: the C Standard also discusses references, but uses the term in a general comp. sci. sense meaning "by pointer". Similarly, it's understandable to ask if `main()` is "overloaded" in C, i.e. compiler generates distinct copies in the executable, and loader decides which to call. General answer: no - only `...(argc, argv[, envp])` compiled/called - unused args ok. But comments on other answers identify instances of this conception of "overloading" - distinct DOS vs Windows entry points. All distinct from C++ overloading, obviously - linker not language resolves the call. – Tony Delroy Jun 21 '11 at 06:31
  • 2
    @Tony, `main` is not really the entry point to the program, it is the first (*main*) function to be called, but static initialization has to occur *before* `main` is called. I doubt that DOS/Windows have different entry points for the applications (it might be if there are different executable formats), and I also doubt that in the case of `wmain`, `_tmain` and `WinMain` the program does not contain a plain `main` function (defined in a library and linked in) that forwards the call... but I would have to have a windows environment to actually test that, so I won't assert that to be true either – David Rodríguez - dribeas Jun 21 '11 at 07:14
  • @David: I'm no expert on Windows either... just discussing the terminology in, and intent and breadth of the question really. iammilind replies in the third comment on his question confirming his intention to use the terminology in a generic way that included "C". – Tony Delroy Jun 21 '11 at 07:48
  • 1
    David's speculations about how Windows entry points work is precisely correct. There's a plain-old `main` function hidden in the library code. The `_tWinMain` stuff that you see is not the official entry point, it's only the entry point as far as *your* code is concerned. – Cody Gray - on strike Jun 22 '11 at 02:40
20

Windows and Unix have:

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

and Win32 apps have:

int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

and MacOS has:

int main(int argc, char **argv, char **envp, char **apple)

Don't forget that main is not usually the first thing the OS calls when executing a program. The main function is the function that is called by the run time environment. The address of the first instruction to execute is usually declared in some meta data, usually at the start if the executable file.

None of the above contradicts the C/C++ standard as far as I can tell, as long as there is only one, which makes sense since the OS wouldn't know which to call if there were more than one. Checking there is only one is not done in the compiler, it is done in the linker.

Skizz
  • 69,698
  • 10
  • 71
  • 108
  • 2
    I'm wondering, can MSVC be seen non-compliant w.r.t. `WinMain`? Since the entry function is defined as `main`... (apart from all the other non-compliant stuff in MSVC.) – Xeo Jun 20 '11 at 08:12
  • 3
    @Xeo: This is basically on the limit... What VS does is creating a `main` function for you, that does some specific initialization before calling your `WinMain` function. The entry point to the program is still `main`, only that in this case it is not *your* main. It seems to contradict with §3.6.1/2 *An implementation shall not predefine the main function.*, but if they can ensure that it will not affect your programs (i.e. if you do define `main` it uses your version and not its own) it might as well behave *as-if*, which is sufficient. – David Rodríguez - dribeas Jun 20 '11 at 08:23
  • 1
    ... and at the same time, other libraries do exactly the same (most unit-test frameworks will provide `main` for you if you want. At that point it becomes a philosophical discussion on whether `main` is generated by the compiler, or linked as a library and all is grey. I would not really care much about it, I have seen worse things elsewhere... Symbian C++ being one of them – David Rodríguez - dribeas Jun 20 '11 at 08:25
  • MSVC also has `int wmain(int argc, wchar_t* argv[]);` and `_tmain` :-./ - see http://stackoverflow.com/questions/895827/what-is-the-difference-between-tmain-and-main-in-c – Tony Delroy Jun 20 '11 at 08:28
  • @David: Well, if a library provides `main` that's a-ok according to the standard. :) – Xeo Jun 20 '11 at 08:32
  • @David Rodríguez: IIRC Win32 apps have two entry points, the WinMain one that Windows uses and a DOS entry point when invoked from DOS (used to just say by default "This program needs Windows", but can be overriden). Not sure which one is used if you define a `main` though. – Skizz Jun 20 '11 at 09:20
  • The actual win32 entry point is (in apps compiled by MSVC - the actual function is specified within the exe) called something like WinMainCrtStartup [it's different if you have WinMain vs main] which is invoked directly by some function in kernel32.dll, and in turn calls WinMain or main or whatever. This is separate from the "DOS stub" you're thinking of that says the program needs windows – Random832 Jun 20 '11 at 13:08
  • `envp` is not guaranteed by the standard. – RastaJedi Mar 17 '19 at 06:53
13

Section 3.6.1.2 of both C++ Standard 1998 and 2003 editions states:

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.

Further,

The ISO C++ Standard (ISO/IEC 14882:1998) specifically requires main to return int. It has an explicit "shall" constraint upon well-formed programs.

Section § 3.6.1 ¶ 2:

It shall have a return type of 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[]) { /* … */ }

So both versions of main are allowed by the standard and which one to use is left as an implementation preference of the programmer.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 1
    Nitpick: usually *implementation detail* is used in the context of the compiler + toolset implementation, while in this case it is up to the user of that implementation to decide: i.e. you the programmer. – David Rodríguez - dribeas Jun 20 '11 at 08:09
  • @David Rodríguez - dribeas: Well pointed out. I had this wee bit of confusion over `implementation detail` being explicitly used in context of compiler & toolset or in a generic way.I changed it, I was about to mention it this way but then I thought of checking out if someone might point out if its wrong to use it in generic way and you did! :) – Alok Save Jun 20 '11 at 08:13
9

Main was defined back in the C days. It's setup more along the rules of printf. Consider main as a varadic function:

int main(...)

The standard says that no arguments and two pointer arguments are okay. However, if the implementation wants to provide more arguments, the implementation is free to do so.

The reason you can't have two mains is the same reason you can't define a printf like function twice in a C program. Sure, printf supports differing arguments and changes it's behavior depending on which arguments are there, but it's not overloading in the C++ sense of the term.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • +1 Good point of reference; focuses attention on distinctions: e.g. `...` allows caller to vary number of arguments, but the OS loader can be expected to always call `main` with the same number of arguments. If the program doesn't explicitly list `(int argc, char* argv[])` most implementations would consider them implicitly there anyway; registers and/or stack that they'd be in are probably loaded with their values prior to calling main. Thankfully you don't get warnings about unused variables :-). So, vs "printf...changes it's behaviour", main's is likely constant (but formally imp. def.) – Tony Delroy Jun 21 '11 at 07:44
7

The standard says that main cannot be overloaded. It isn't mangled, and you cannot have two functions with the same unmangled name. This will cause a linking failure, I guess, but a compiler could want to add explicit checks in order to give clearer error messages.

int main(int argc, char **argv) and int main() should be the preferred signatures for it, but compilers are free to accept a main with different parameters.

peoro
  • 25,562
  • 20
  • 98
  • 150
  • Does that mean that `main` is always declared `extern "C"`, whether or not you write that explicitly? – Kerrek SB Jun 20 '11 at 07:56
  • @iammilind: I have not been able to detect such requirement in the standard, and I would be surprised if it was present, since you cannot call `main` directly from any context, not even the OS, as the OS must call the specially generated static initialization code before main --i.e. it is an implementation detail how it is mangled or not, it could have special mangling or no mangling at all. – David Rodríguez - dribeas Jun 20 '11 at 08:04
  • @David, I haven't referred to standard, but I am saying based on the observation. 1st thing is that `main()` doesn't get name mangled until it's in global scope and 2nd thing is that when you declare multiple `main()` with different arguments in one file, compiler gives error as: `error: declaration of C function int main() conflicts with ...` – iammilind Jun 20 '11 at 08:13
  • 1
    @iammilind: That only means that your compiler in your platform treats `main` as a C function, not that in general "it's not mangled as it's considered a C function" or that "it's always `extern "C"`". In particular, in a platform (OS) that *called* a C style function `main` as entry point to the program, a C++ compiler would be forced to mangle your `main` function to something different, and add static initialization to the `_main` symbol. The reason that this is not specified is because this is dealing with the interface with the OS, and the C++ standard cannot mandate what to do there. – David Rodríguez - dribeas Jun 20 '11 at 08:16
0

It is not possible to overload main() in C++ because. the compiler shown the following error:

error C2731: 'main' : function cannot be overloaded 
theChrisKent
  • 15,029
  • 3
  • 61
  • 62