Why this code prints 1 instead of 5
Code:
main(int x=5) //this defn. is written intentionally to chec weather main accepts
expression or not.
{
printf("%d",x);
}
Compiler used:minGW 3.2
EDIT
My point is weather x=5 executes or not. if not then why i don't get any error or warning.
because x is really argc (and your count of arguments is 1)
The signature for main is:
int main (int argc, char **argv)
with argc being a count of arguments
and argv being an array of those arguments
In void f(int x = 5), the = 5 part is a default argument. You can call the function in two different ways:
f(); // uses default argument, as if f(5)
f(3); // explicit argument
Note that the decision to use the default argument is made at the point of the call, not at the point of the declaration. Regardless of whether int main(int x = 5, char *argv[]) is valid, the application's startup code (part of the compiler's library) won't know about the attempted default argument, so won't do anything with it. And don't try and get tricky by calling main from inside your program: that's not allowed.
Update
Your main declaration is not valid, if we look at the C++ draft standard section 3.6.1 Main function paragraph 2 says(emphasis mine):
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
— a function of () returning int and
— a function of (int, pointer to pointer to char) returning int
So main should adhere to one of these standard forms or implementation defined forms defined by compiler documentation.
gcc gives me a warning for this regardless of warning levels and in clang this is an error, so I am not sure why you do not see an error.
Orignal Answer
The first argument to main is the argument count usually denoted as argc for example:
int main(int argc, char *argv[])
{
}
and argv is an array of string which represents the arguments to your program, the first one being the command line.
Because the operating system expects this signature of main:
int main(int argc, char** argv);
argc is the amount of parameters. When it calls your main, it passes the amount of arguments (argc) as the first parameter, which is 1 (if you call your binary without arguments, you still get one argument: the binary filename, $0 in bash).
Note that this depends also on the C ABI. By the C/C++ standard, multiple signatures of main are allowed. So, depending on the compiler and the OS, there could be a different handling for main. What you are doing is not really defined behavior.
You should declare main like the expected - because that is what your OS expects and uses. Make another function for whatever you want to program.
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.
int main( const int argc , const char[] const argv)
As Effective C++ Item#3 states "Use const whenever possible", I start thinking "why not make these 'constant' parameters const"?.
Is there any scenario in which the value of argc is modified in a program?
In this case, history is a factor. C defined these inputs as "not constant", and compatibility with (a good portion of) existing C code was an early goal of C++.
Some UNIX APIs, such as getopt, actually do manipulate argv[], so it can't be made const for that reason also.
(Aside: Interestingly, although getopt's prototype suggests it won't modify argv[] but may modify the strings pointed to, the Linux man page indicates that getopt permutes its arguments, and it appears they know they're being naughty. The man page at the Open Group does not mention this permutation.)
Putting const on argc and argv wouldn't buy much, and it would invalidate some old-school programming practices, such as:
// print out all the arguments:
while (--argc)
std::cout << *++argv << std::endl;
I've written such programs in C, and I know I'm not alone. I copied the example from somewhere.
The C standard (ISO/IEC 9899:2011) says:
5.1.2.2.1 Program startup
¶1 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;10) or in some other implementation-defined manner.
¶2 If they are declared, the parameters to the main function shall obey the following
constraints:
The value of argc shall be nonnegative.
argv[argc] shall be a null pointer.
If the value of argc is greater than zero, the array members argv[0] through
argv[argc-1] inclusive shall contain pointers to strings, which are given
implementation-defined values by the host environment prior to program startup. The
intent is to supply to the program information determined prior to program startup
from elsewhere in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the implementation
shall ensure that the strings are received in lowercase.
If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0] shall be the null character if the
program name is not available from the host environment. If the value of argc is
greater than one, the strings pointed to by argv[1] through argv[argc-1]
represent the program parameters.
The parameters argc and argv and the strings pointed to by the argv array shall
be modifiable by the program, and retain their last-stored values between program
startup and program termination.
10) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as
char **argv, and so on.
Note the last bullet point. It says that both argc and argv should be modifiable. They don't have to be modified, but they may be modified.
argc is not normally a constant because the function signature for main() pre-dates const.
Since argc is a stack variable, changing it won't affect anything other than your own command line processing.
You are, of course, free to declare it const if you want.
A top level const on a formal argument is not part of the function type. You can add it or remove it as you like: it only affects what you can do with the argument in the function implementation.
So for argc you can add freely add a const.
But for argv you can not make the character data const without thereby changing the function signature. Which means that it's then not one of the standard main function signatures, and will not have to be recognized as a main function. So, not a good idea.
A good reason for not using the standard main arguments in non-toy programs is that in Windows they are not able to represent actual program arguments such as filenames with international characters. That's because in Windows they are by very strong convention encoded as Windows ANSI. In Windows you can implement some more portable argument access facility in terms of the GetCommandLine API function.
Summing up, nothing prevents you from adding const to argc, but the most useful const-ness on argv would give you a non-standard main function, most probably not recognized as such. Happily (in an ironic way) there are good reason to not use the standard main arguments for portable serious code. Quite simply, for the in-practice they only support old ASCII, with only English alphabet letters.
The signature of main is somewhat of a historical artifact from C. Historically C did not have const.
However, you can declare your parameter const since the effects of const are compile time only.
Because argc is a local variable (and, in C++, not a reference or something), and because the special place of main means that backwards compatibility shenanigans grant it a huge amount of leeway with no compelling reason to force applications to make it const.
main() {}
int main() {}
main() { return 0; }
main(int argc, char* argv[]) { return 0; }
int main(const int argc, const char** argv) { /* no return*/ }
these and many other variations will compile on a wide range of C and C++ compilers.
So ultimately it's not that argc isn't const, just that it doesn't have to be, but it can be if you want it to be.
http://ideone.com/FKldHF, C example:
main(const int argc, const char* argv[]) { return 0; }
http://ideone.com/m1qc9c, C++ example
main(const int argc) {}
Aside from the historical reasons, a good reason to keep argc and argv non-const is that the compiler implementation doesn't know what you're going to do with the arguments to main, it just knows that it must give you those arguments.
When you are defining your own functions and associated prototypes, you know which parameters you can make const and which ones your function will modify.
Taken to an extreme, you could declare that all parameters to all functions should be declared const, and then if you had a reason to change them (e.g. decrement an index to search through an array), you'd have to make local non-const variables and copy the const arguments' values into those variables. That makes for busy-work and extra LOC with no real benefit. A decent static analyzer will pick up if you're not modifying the value of an argument, and recommend that you make the parameter const.
This question already has answers here:
in c: func(void) vs. func() [duplicate]
(2 answers)
Closed 9 years ago.
I have seen some code in C/C++ that goes like this:
void Main(void)
And
int Main(void)
What is the reasoning for this: why is it not a parameter but used in parentheses after the void/int e.t.c name?
void in a parameter list is effectively a keyword, not specifying the type of anything. The reason for its existence is purely historical.
Early C did not have function prototypes or any syntax for parameter lists. A function definition would look like this:
foo()
int x; // These are the parameters.
float y;
{
return x + (int) y;
}
There was "no need" for prototypes because the compiler would assume every call passed exactly the correct type and number of arguments. This was error-prone. Furthermore the return type was assumed to be int, which is an even more brittle assumption. The first prototypes specified only the return type.
float foo(); // Still no parameters.
When the familiar float foo( int x, float y ) syntax was introduced, backward compatibility with the preceding style was retained. The void keyword was used to differentiate between an indeterminate (missing) parameter list and an empty parameter list.
In C, float foo() and float foo( void ) mean different things to this day.
In C++, indeterminate parameter lists are unsupported, and float foo( void ) is a discouraged, but not deprecated, synonym for float foo().
Furthermore C++ allows templates to determine the type of an argument, but generating a (void) parameter list by a template is an error.
In C (void) means that there is no arguments required in function call, while () means unspecified number of arguments. In C++. () means the same as (void)
Here is what C standard says
5.1.2.1 Freestanding environment
In a freestanding environment (in which C program execution may take
place without any benefit of an operating system), the name and type
of the function called at program startup are implementation-defined.
/ .. / The effect of program termination in a freestanding environment
is implementation-defined.
5.1.2.2 Hosted environment
A hosted environment need not be provided, but shall conform to the
following specifications if present.
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[]) { /* ... */ }
In C this
void func() {
}
means a function that takes an indeterminate number of arguments. If you want to write a function that takes zero arguments you do this
void func(void) {
}
The reasons for this are in the history of the C language, they don't make much sense otherwise. For this reason C++ changed the rules. In C++ the first example above means a function that takes zero arguments, and this
void func(int x, ...) {
}
means a function that takes a variable number of arguments (one or more in this case). C will also accept this.
So in C and C++, example 2 means zero arguments and example 3 means a variable number of arguments, but C and C++ disagree on what example 1 means, for C it's an indeterminate number of arguments, for C++ it's zero arguments.
If you see (void) in a C++ program it's either code that has been ported from C and no-one has bothered to change it, or it's code which is expected to be compiled as both C and C++ (in a header file for instance).
Draft n1570;
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.....)
It is clear from the C standard that void is used for a function having no parameter.
In c++, sometimes parameter "names" may be excluded if they are not called from within the function. If you know that you will use it, you may add the parameter name by yourself. It would hardly make sense for the void parameter of main, though.
In old compilers it was mandate to specify void in parenthesis in case main is not going to accept any parameters. but these days you may need to use like only:
void main()
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.
This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 5 years ago.
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?
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. ]
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.
The argv pointers shouldn't be const char* const because the program is allowed to change the buffers.
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.
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.
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?
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.