Is int main(int, char const* const*) well formed? - 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.

Related

using const variables as non type template arguments

I have a question on using a const variable as a template argument.
The following compiles fine using gcc and clang x64 trunk:
template <int N>
void func() { }
int main(int argc, char *argv[]) {
const int x = 12;
func<x>();
}
However, and as one might expect, this version of main() does not compile:
int main(int argc, char *argv[]) {
const int x = argc;
func<x>();
}
Shouldn't x be required to be constexpr? Or, is const implicitly constexpr when the value can be determined at compile time?
Normally, a variable has to be marked constexpr if you want to use its value in a constant expression (meaning, in compile-time evaluation), as is required by a template argument.
However, there is an exception for const integral and enumeration types, which are also allowed to be used in that way, assuming that they themselves are initialized with a constant expression.
In your first example, x is initialized with a constant expression. In your second example, it clearly isn't (because argc is a function parameter).
This exception has historical reasons. It was already possible to use const integral/enumeration variables in this way before constexpr was invented (which first appearing in C++11). Without such a rule, there wouldn't have been any way to provide named non-type template arguments or array bounds before C++11, other than by a preprocessor macro (as is the case for C without VLAs). And, because old code shouldn't break needlessly with new C++ versions, this exception is still in place.

LNK2019 unresolved external symbol _main referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ) [duplicate]

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.

Type definition of command line arguments (argc, argv, args) [duplicate]

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.

Can we add CV-qualifiers to the arguments of main?

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

why initializer list cannot be main's parameter? how to propose it?

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.