19

Being a low-level programmer, I often work with the module startup code for executables, so I understand pretty well how code like "crt0" work. When writing C++ code, I've generally declared main as extern "C" to match what the C startup code is going to do to call main. I thus usually use this declaration for main (and wmain if specifically targeting Windows):

extern "C" int main(int argv, const char *const *argv)

extern "C" int __cdecl wmain(int argv, const wchar_t *const *argv)

Is it legal to use extern "C" on main? Also, is const char *const * legal for argv's type as opposed to char *[]?

Myria
  • 3,372
  • 1
  • 24
  • 42
  • 2
    `const char *const *argv` should be legal, though you might want to keep it at `char *const *argv` for practical reasons, specifically the fact that if you ever use getopt or similar, that first const will kill you. – Charlie Nov 06 '13 at 03:29
  • You don't actually want the C startup code. You need to run the constructors of globals to run, and that's done by the C++ startup code. The other way around, usually no problems exist. There's nothing in the C language that causes problems for C++ startup code. – MSalters Nov 06 '13 at 09:06
  • See also [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/). – Jonathan Leffler May 31 '16 at 02:27

3 Answers3

6

The linkage is implementation defined (3.6.1p3):

The linkage (3.5) of main is implementation-defined.

Also, for your latter question, that is perfectly acceptable to have const char* const* (3.6.1p2):

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.

Jesse Good
  • 50,901
  • 14
  • 124
  • 166
5

extern "C" only tells the C++ compiler specifically to NOT decorate or use name wrangling on generated function labels.

Yes, both are legal.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • Actually, it can also change the calling convention: default C++ calling convention doesn't have to be compatible with the C one, only `extern "C"` enforces that. – syam Nov 06 '13 at 03:29
  • "default C++ calling convention doesn't have to be compatible with the C one", really? any citation? To my knowledge, being compatible with C is one of the main aims of C++. @syam – xmllmx Dec 26 '19 at 14:11
4

The standard blesses two forms of main:

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

These forms are what any implementation must recognize. Everything else is your implementation being easy with your code and letting you be creative. It is not illegal, as the standard specifically allows it to recognize other forms of main.

The startup code is normally written in a way that allows it to call main having no linkage declaration, because that's how the standard says main should be. The compiler usually treats main specially as having C linkage, as allowed by the standard, so that's how the startup code declares it. This is of no interest to a normal programmer. He just needs to follow the standard.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Windows in particular seems to treat `main()` as `extern "C" void __cdecl main()`, and the MS-specific `WinMain()` as `extern "C" void __stdcall WinMain()`, judging by the mangled names (`_main` and `_WinMain@16`, respectively). I suspect it's a limitation of the CRT being designed to work with both C and C++ code. [`wmain` and `wWinMain` are treated identically to `main` and `WinMain`.] – Justin Time - Reinstate Monica May 05 '16 at 17:06