As far as I know, in C or C++, the signature of main should either be int main(void) (void is optional in C++) or int main(int, char**). However, the following code compiles with no warnings (-Wall -Wextra -Wpedantic) in gcc/g++/clang/clang++
int main(int, const char * const * const argv){}
Live on Coliru
Is the code above legal? In other words, can we add CV-qualifiers to the arguments of main, or is this just an extension of the compiler that requires no diagnostic?
The C++11 Standard allows the implementation to accept any signature it likes it only mandates the two presented in question. It must also have a return type of int.
3.6.1 Main Function [basic.start.main]
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[]) { /* ...
*/ }
So to address the main question:
Can we add CV-qualifiers to the arguments of main?
We can if the implementation supports it but if we do then the code is less likely to be portable.
The code will only be fully portable if it adds (at most) cv qualifiers to the parameter variable itself, not its pointed-to types:
// still portable, same signature as int main(int, char**)
int main(int, char** const argv);
// not portable
int main(int, char* const* argv);
// not portable
int main(int, const char** argv);
Remember that C and C++ are two distinct languages. The answer happens to be pretty much the same for both, but it's worth covering what the C standard says as well -- especially given the language-lawyer tag. The link is to the N1570 draft of C11.
Section 5.1.2.2.1 covers the definition of main for hosted implementations:
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; or in some other implementation-defined manner.
A definition with added const or volatile qualifiers is not equivalent to the forms shown, so an implementation is not obliged to accept it. But since that section is not a constraint, an implementation is not required to complain about it either. And in particular, if an implementation documents that it accepts const and/or volatile qualifiers, then they're perfectly valid for that implementation.
(In practice, most compilers probably won't complain.)
Note that this applies only to hosted implementations. For a freestanding implementation (typically for an embedded target with no OS):
... the name and type of the function called at program
startup are implementation-defined.
(5.1.2.1 paragraph 1) which means that there are no portable definitions of the main function for freestanding implementations (it needn't even be called main).
Related
Questions
What is the proper signature of the main function in C++?
What is the correct return type, and what does it mean to return a value from main?
What are the allowed parameter types, and what are their meanings?
Is this system-specific?
Have those rules changed over time?
What happens if I violate them?
The main function must be declared as a non-member function in the global namespace. This means that it cannot be a static or non-static member function of a class, nor can it be placed in a namespace (even the unnamed namespace).
The name main is not reserved in C++ except as a function in the global namespace. You are free to declare other entities named main, including among other things, classes, variables, enumerations, member functions, and non-member functions not in the global namespace.
You can declare a function named main as a member function or in a namespace, but such a function would not be the main function that designates where the program starts.
The main function cannot be declared as static or inline. It also cannot be overloaded; there can be only one function named main in the global namespace.
The main function cannot be used in your program: you are not allowed to call the main function from anywhere in your code, nor are you allowed to take its address.
The return type of main must be int. No other return type is allowed (this rule is in bold because it is very common to see incorrect programs that declare main with a return type of void; this is probably the most frequently violated rule concerning the main function).
There are two declarations of main that must be allowed:
int main() // (1)
int main(int, char*[]) // (2)
In (1), there are no parameters.
In (2), there are two parameters and they are conventionally named argc and argv, respectively. argv is a pointer to an array of C strings representing the arguments to the program. argc is the number of arguments in the argv array.
Usually, argv[0] contains the name of the program, but this is not always the case. argv[argc] is guaranteed to be a null pointer.
Note that since an array type argument (like char*[]) is really just a pointer type argument in disguise, the following two are both valid ways to write (2) and they both mean exactly the same thing:
int main(int argc, char* argv[])
int main(int argc, char** argv)
Some implementations may allow other types and numbers of parameters; you'd have to check the documentation of your implementation to see what it supports.
main() is expected to return zero to indicate success and non-zero to indicate failure. You are not required to explicitly write a return statement in main(): if you let main() return without an explicit return statement, it's the same as if you had written return 0;. The following two main() functions have the same behavior:
int main() { }
int main() { return 0; }
There are two macros, EXIT_SUCCESS and EXIT_FAILURE, defined in <cstdlib> that can also be returned from main() to indicate success and failure, respectively.
The value returned by main() is passed to the exit() function, which terminates the program.
Note that all of this applies only when compiling for a hosted environment (informally, an environment where you have a full standard library and there's an OS running your program). It is also possible to compile a C++ program for a freestanding environment (for example, some types of embedded systems), in which case startup and termination are wholly implementation-defined and a main() function may not even be required. If you're writing C++ for a modern desktop OS, though, you're compiling for a hosted environment.
From Standard docs., 3.6.1.2 Main Function,
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.....
Hope that helps..
The exact wording of the latest published standard (C++14) is:
An implementation 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.
This makes it clear that alternative spellings are permitted so long as the type of main is the type int() or int(int, char**). So the following are also permitted:
int main(void)
auto main() -> int
int main ( )
signed int main()
typedef char **a; typedef int b, e; e main(b d, a c)
The two valid mains are int main() and int main(int, char*[]). Any thing else may or may not compile. If main doesn't explicitly return a value, 0 is implicitly returned.
Details on return values and their meaning
Per 3.6.1 ([basic.start.main]):
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 behavior of std::exit is detailed in section 18.5 ([support.start.term]), and describes the status code:
Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.
Questions
What is the proper signature of the main function in C++?
What is the correct return type, and what does it mean to return a value from main?
What are the allowed parameter types, and what are their meanings?
Is this system-specific?
Have those rules changed over time?
What happens if I violate them?
The main function must be declared as a non-member function in the global namespace. This means that it cannot be a static or non-static member function of a class, nor can it be placed in a namespace (even the unnamed namespace).
The name main is not reserved in C++ except as a function in the global namespace. You are free to declare other entities named main, including among other things, classes, variables, enumerations, member functions, and non-member functions not in the global namespace.
You can declare a function named main as a member function or in a namespace, but such a function would not be the main function that designates where the program starts.
The main function cannot be declared as static or inline. It also cannot be overloaded; there can be only one function named main in the global namespace.
The main function cannot be used in your program: you are not allowed to call the main function from anywhere in your code, nor are you allowed to take its address.
The return type of main must be int. No other return type is allowed (this rule is in bold because it is very common to see incorrect programs that declare main with a return type of void; this is probably the most frequently violated rule concerning the main function).
There are two declarations of main that must be allowed:
int main() // (1)
int main(int, char*[]) // (2)
In (1), there are no parameters.
In (2), there are two parameters and they are conventionally named argc and argv, respectively. argv is a pointer to an array of C strings representing the arguments to the program. argc is the number of arguments in the argv array.
Usually, argv[0] contains the name of the program, but this is not always the case. argv[argc] is guaranteed to be a null pointer.
Note that since an array type argument (like char*[]) is really just a pointer type argument in disguise, the following two are both valid ways to write (2) and they both mean exactly the same thing:
int main(int argc, char* argv[])
int main(int argc, char** argv)
Some implementations may allow other types and numbers of parameters; you'd have to check the documentation of your implementation to see what it supports.
main() is expected to return zero to indicate success and non-zero to indicate failure. You are not required to explicitly write a return statement in main(): if you let main() return without an explicit return statement, it's the same as if you had written return 0;. The following two main() functions have the same behavior:
int main() { }
int main() { return 0; }
There are two macros, EXIT_SUCCESS and EXIT_FAILURE, defined in <cstdlib> that can also be returned from main() to indicate success and failure, respectively.
The value returned by main() is passed to the exit() function, which terminates the program.
Note that all of this applies only when compiling for a hosted environment (informally, an environment where you have a full standard library and there's an OS running your program). It is also possible to compile a C++ program for a freestanding environment (for example, some types of embedded systems), in which case startup and termination are wholly implementation-defined and a main() function may not even be required. If you're writing C++ for a modern desktop OS, though, you're compiling for a hosted environment.
From Standard docs., 3.6.1.2 Main Function,
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.....
Hope that helps..
The exact wording of the latest published standard (C++14) is:
An implementation 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.
This makes it clear that alternative spellings are permitted so long as the type of main is the type int() or int(int, char**). So the following are also permitted:
int main(void)
auto main() -> int
int main ( )
signed int main()
typedef char **a; typedef int b, e; e main(b d, a c)
The two valid mains are int main() and int main(int, char*[]). Any thing else may or may not compile. If main doesn't explicitly return a value, 0 is implicitly returned.
Details on return values and their meaning
Per 3.6.1 ([basic.start.main]):
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 behavior of std::exit is detailed in section 18.5 ([support.start.term]), and describes the status code:
Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.
The valid C++ main signatures are the following:
int main()
int main(int argc, char *argv[])
int main(int argc, char **argv)
But isn't allowed to declare main taking an initializer list:
int main(std::initializer_list<char *> args)
AFAIK the initializer list could be implemented as a pair of pointers or a pointer (this could be the argv parameter) plus a length (this could be deduced from the argc parameter), and its storage could be automatic, temporary, or static read-only memory depending on the situation.
So i think that an std::initializer_list<char *> could handle and manage without any problem the command line parameters, then i'm wondering why this hypothetical main signature wasn't added after the approval of the initializer lists on the C++11 standard, and because of that i'm asking:
What could be the disadvantages or problems derived of allowing an initializer list as the main only parameter? (i couldn't think of any).
Which would be the correct way to propose to the standards committee this addition (or any other change)?
Although there are two ways of specifying main() in a program, most (all?) current implementations of the C++ run-time call the main() function the same way (they pass the arguments as (int, char *[]) irrespective to how main() is declared). Your proposal would require the C++ run-time of all implementations to figure out which kind of main() the program is using, and call the right main(). If you really want this functionality for yourself, you can always provide an implementation of main(int, char *[]) that converts the arguments into an initializer list like object (such as vector<>), and then calls a new entry point function of your choice.
The process for submitting a proposal is described at the Standard C++ website. The basic steps are: (1) float the idea on their Usenet group/mailing list; (2) draft a proposal, solicit feedback, and update the proposal accordingly; and (3) repeat the process until the proposal is accepted.
It is worth noting that a library (but not the standard C++ library according to 3.6.1 [basic.start.main] paragraph 2, first sentence: "An implementation shall not predefine the main function.") could just define function main() and implement it in a suitable way, e.g., calling app_main():
#include <initializer_list>
#include <string>
#include <vector>
extern int app_main(std::vector<std::string> const&);
int main(int ac, char* av[]) {
return app_main(std::vector<std::string>(av, av + ac));
}
Since main() can't be overloaded (according to 3.6.1 [basic.start.main] paragraph 2, second sentence: "This function shall not be overloaded.") the entry point needs a different name. Since std::initializer_list<T> cannot be constructed other than using { ... }, a different type than std::initializer_list<T> needs to be used. While being at it, the above implementation also chooses to turn the char* into std::string objects.
To use the above function, an application would just implement app_main() and it would get called:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
int app_main(std::vector<std::string> const& args) {
std::cout << "received the arguments: ";
std::copy(args.begin(), args.end(),
std::ostream_iterator<std::string>(std::cout, " "));
return EXIT_SUCCESS; // return statement can't be omitted, of course
}
I think it is due to the considerations of the C compatibility and not the technical reasons. There are a lot stuff inherited from C.
According to the C++11 standard, is the following program well-formed and portable C++?
int main(int argc, char const* const* argv) {}
No. In a pure portable C++ program, the argv argument, if present, has no const modifiers.
Edit: See section 3.6.1.2 of the C++11 draft standard, which (in the version I have before me) 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. All implementations
shall allow both of the following definitions of main:
int main(){ /*...*/ }
and
int main(int argc, char* argv[]) { /* ... */ }
Depends on what you mean by portable. An evil C++ implementation could reject it on the grounds that its signature, int(int,char const*const*), is different from one of the required allowed signatures, int() and int(int,char**). (An evil implementation could seemingly reject auto main(int argc,char* argv[]) -> int or, indeed, any definition of main where the body isn't { /* ... */ })
However this isn't typical. I don't know of any implementations where adding a const would cause a problem calling main, and since C++11 added the bit about 'similar' types you won't violate the strict aliasing rule when accessing a char** object through a char const * const * variable.
So while a conforming implementation could technically reject it, I think it will be portable to any implementation you might care to use.
This question already has answers here:
Can main function call itself in C++?
(9 answers)
Closed 4 years ago.
I read that the C++ standard forbids recursion in main(), but g++ compiles the following code without complaint:
int main()
{
main();
}
Can anyone clarify this?
According to the standard in 3.6.1/3, it's not :
The function main shall not be used
(3.2) within a program
The definition of used being :
An object or non-overloaded
function is used if its name appears in a potentially-evaluated expression.
I'll do the fish and explain why this is verboten. Before a C or C++ program can start running, the CRT has to be initialized first. Open stdin/out/err, call initializers, that sort of thing. There are two basic strategies to get this done, a heavy platform implementation detail.
The program's start address points to the CRT init function, which eventually calls main(). Common on full-featured operating systems that have a fancy loader which can support arbitrary sections in the executable image.
The compiler injects code into the main() function that calls the CRT initialization function. The start function is always main(). Common on embedded platforms with limited loader capabilities. Recursing main() is now a problem, the CRT startup code will be called again with an unpredictable stack state.
The claim here is that it is indeed specifically forbidden:
Well, the standard states:
3.6.1.3
"The function main shall not be used within a program."
5.2.2.9
"Recursive calls are permitted, except to the function named main"
You can, of course, do this:
int main(int argc, char* argv[]) {
return foo(argc, argv);
}
int foo(int argc, char* argv[]) {
if (some_condition) {
return foo(argc, argv);
}
return 0;
}
(Note I added a get-out clause. I can't even hypothetically code infinite recursion, it repeats on me.)
It is not legal. Read 3.6.1-3 :
The function main shall not be used
(3.2) within a program. The linkage
(3.5) of main is
implementation-defined. A program that
declares main to be inline or static
is ill-formed. The name main is not
otherwise reserved. [Example: member
functions, classes, and enumerations
can be called main, as can entities in
other namespaces. ]
Other people have addressed the standards part. However, I'd like to note that g++ (at least 4.6.2) will reject this if you use -pedantic-errors with at least one of these errors (depending on main signature):
error: ISO C++ forbids calling ‘::main’ from within program [-pedantic]
error: ISO C++ forbids taking address of function ‘::main’ [-pedantic]