28

The standard explicitly states that main has two valid (i.e., guaranteed to work) signatures; namely:

int main();
int main(int, char*[]);

My question is simple, would something like the following be legal?

int main(const unsigned int, const char* const* argv);

My tests say 'yes', but I'm unsure of the answer because am I not overloading main by changing int to unsigned int as well as the non top-level const-ness of argv? If I am, then that's clearly prohibited.

So, are these modifications guaranteed to work on a standards conforming compiler?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
bh9042
  • 291
  • 1
  • 3
  • 5
  • 7
    why would you want to do something like that? Just write standard-conforming code – Glen Oct 25 '09 at 18:09
  • 11
    Glen, I _want_ to write conforming code. That's why I asked this question in the first place. – bh9042 Oct 25 '09 at 18:22
  • 9
    Then declare `int main(int, char **)` and be on your way. – Jed Smith Oct 25 '09 at 18:23
  • 4
    Again, I was hoping that someone could quote the standard or something and show me that this is illegal. I realize that main's signature is ancient and it's been done this way forever, but I couldn't care less what people are used to. I was hoping for a concrete answer. =\ – bh9042 Oct 25 '09 at 18:28
  • 4
    @bh9042, but you know what the conforming code is, you posted it yourself. As the second piece of code you posted isn't either of the 2 conforming signatures for main then it's obviously not conforming to the standard. And just because most compilers let you away with the non-conforming code now, it doesn't mean that they'll let you do it in the next version – Glen Oct 25 '09 at 18:38
  • More generic question: http://stackoverflow.com/questions/4207134/what-is-the-proper-declaration-of-main – Ciro Santilli OurBigBook.com Apr 26 '15 at 12:11

7 Answers7

33

The C++98 standard says in section 3.6.1 paragraph 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 the following definitions of main: int main() and int main(int argc, char* argv[])

So it's not mandated by the standard that the env accepting main is acceptable but it is permissible.


Because this is referred to often, here is the previous paragraph exempting freestanding environments from anything but documenting their behavior:

A program shall contain a global function called main, which is the designated start of the program. It is implementation defined whether a program in a freestanding environment is required to define a main function. [Note: in a freestanding environment, startup and termination is implementation defined; startup contains the execution of constructors for objects of namespace scope with static storage duration; termination contains the execution of destructors for objects with static storage duration. ]

Motti
  • 110,860
  • 49
  • 189
  • 262
20

You must use one of the standard-conformant signatures to be standard-conformant.

I fully understand why you want to do it your way. The best way is to write your own function myMain() or whatever with the signature you want and call it from main(), including the required casts.

mh.
  • 650
  • 4
  • 8
2

The argv pointers shouldn't be const char* const because the program is allowed to change the buffers.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
1

As far as I can see from reading the standard, you're being non-standards-compliant. But I can't imagine a compiler that wouldn't let you do this. As in, it'd take more work from the compiler to specifically ban an edge case that is mostly harmless and very obscure.

pavpanchekha
  • 2,073
  • 1
  • 17
  • 23
  • Amen. your code MAY have issues compiling on a hypothetical compiler that 100% follows the standard. But most compilers do not, and this edge case is probably one of those where they allow what is technically an illegal behavior. – DVK Oct 25 '09 at 18:15
1

This may not work if the compiler uses name mangling for main. It's a C++ function after all. Hence, the linker will be looking for two particular "manglings". Your definition would have another mangled name.

Note that main is special (doesn't overload, not callable) and might not require name mangling at all.

MSalters
  • 173,980
  • 10
  • 155
  • 350
0

You might be illegal by the standard, but most runtimes don't really care. They'll just push an integer for argc and a pointer for argv, call your main, and hope you parse them right. So, in your purview, "guaranteed to work" is debatable as the loader really doesn't care what you've declared the arguments as.

If it builds, main will get called. How you parse the arguments is up to you. I should clarify that this is highly platform-specific, as is nearly this entire question.

That said, why?

Jed Smith
  • 15,584
  • 8
  • 52
  • 59
  • 1
    1. argc is guaranteed to be non-negative, I want to see an unsigned somewhere in there... ;) 2. I want the extra safety net that const provides against stupid mistakes. Like I responded to jeffamaphone, even though I'm allowed to change argv, I don't want or need to. – bh9042 Oct 25 '09 at 18:19
  • 1
    `main` predates C++, and even the time of `unsigned`. Regardless of what you want, `main` has been declared this way for a long, long time. You really need the compiler to protect you from modifying `argv`? If you don't have that `const` there are you accidentally going to replace all the '-' with '/' in your `argv` strings? You're not selling me on why this is needed. – Jed Smith Oct 25 '09 at 18:21
  • 1
    I think it's a valid point that allowing programmers to specify assumptions and constraints through modifiers like `unsigned` and `const` should be allowed anywhere. If it's good for user-defined functions, I don't see why it wouldn't be good for `main()` too. – Andrew Coleson Oct 25 '09 at 19:14
  • 3
    afaics, there is nothing platform specific in this question. – Johannes Schaub - litb Oct 26 '09 at 02:24
0

ISO/IEC 9899:TC3

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

thkala
  • 84,049
  • 23
  • 157
  • 201
KedarX
  • 763
  • 1
  • 7
  • 15