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()
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.
While going through some allegro tutorials I found an odd call.
int al_init();
The function al_init() initializes allegro so that the allegro functions can be used. What is with the int al_init(); line? If I change this line of the code to exclude int it works the same, but if I take out the line altogether it does not work. What is this line doing? The only thing I can imagine is that it creates an integer and assigns it the return value of the al_init() function, with that likely being -1 for failure and 0 for success etc. But if that is what this is doing, then how can you even check the return value?
In C/C++ there are function declarations and function definitions:
Declarations look like these:
int a_function();
void another_function();
double yet_another_function();
Explanation:
The identifier before the function name (e.g. int, void, double) describes the type of value returned by the function.
If you do not specify one, it defaults to int (which is why it works when you remove int from int al_init(), but not when you remove the declaration altogether)
void means it's not supposed to return a value (even though technically it can, but that's for rarer cases)
Definitions look like these:
int a_function() {
std::cout << "hello world!";
int x = 1;
int y = 2;
return (x + y);
}
Notice the difference:
Declarations end with ;
Definitions are followed by a block of code enclosed by braces: { and }, but no ;!
In some cases, you do not need to declare a function. If it's at a point in the code where the definition has already been seen, the definition can substitute for the declaration (this leads us to the next point...)
The purpose of declaration is to tell the program that, for example, there is a function named a_function, it expects no arguments, and it returns a value of type int.
Are you sure you aren't looking at the function declaration?
According to C's syntactic rules, a prototype is defined as:
<return-type> function-name (param1, param2, ..);
And a function call is defined as:
function-name(param1, param2,...);. So its obviously defining a function prototype and NOT calling the function.
C89 and previous rules were:
With the above rule, another rule was:
For implicit integer return type, the prototype was suppose to be defined outside of any executable function code. If it was inside of a function, it would be called a function-call and not function-prototype-definition.
That aside, lets start with the question:
While going through some allegro tutorials I found an odd call. int
al_init();
That's incorrect, it looks like a function prototype or declaration
The function al_init() initializes allegro so that the allegro
functions can be used. What is with the int al_init(); line? If I
change this line of the code to exclude int it works the same, but if
I take out the line altogether it does not work.
What does not work? Stops to compile? That would be obvious because it will not be able to find al_init() function. Also the reason it works without the "int" is because its implicitly assumed to return an integer.
What is this line doing?
Its telling the compiler that al_init() library function is defined elsewhere, typically in a .lib or .a or .dll, and you would want to use it in your program.
The only thing I can imagine is that it creates an integer and assigns
it the return value of the al_init() function,
Absolutely incorrect interpretation of code, it does not create any integer, nor assigns any value to it.
with that likely being -1 for failure and 0 for success etc. But if
that is what this is doing, then how can you even check the return
value?
Since you want to know what that function returned, you could do this while an actual call to al_init():
int retval = al_init();
printf("al_init() returned %d",retval);
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:
Closed 12 years ago.
Possible Duplicate:
does c++ standard prohibit the void main() prototype?
Why is C++ not letting me do void main()? It's not much of a problem, but I'm still curious.
Because return type of main()(as mandated by the Standard) must be int
C++03 [Section 3.6.1 Main function]
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.
Answer from Stroustrup himself:
Can I write "void main()"?
The definition
void main() { /* ... */ }
is not and never has been C++, nor has it even been C. See the ISO C++ standard 3.6.1[2] or the ISO C standard 5.1.2.2.1. A conforming implementation accepts
int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }
A conforming implementation may provide more versions of main(), but they must all have return type int. The int returned by main() is a way for a program to return a value to "the system" that invokes it. On systems that doesn't provide such a facility the return value is ignored, but that doesn't make "void main()" legal C++ or legal C. Even if your compiler accepts "void main()" avoid it, or risk being considered ignorant by C and C++ programmers.
In C++, main() need not contain an explicit return statement. In that case, the value returned is 0, meaning successful execution. For example:
#include<iostream>
int main()
{
std::cout << "This program returns the integer value 0\n";
}
Note also that neither ISO C++ nor C99 allows you to leave the type out of a declaration. That is, in contrast to C89 and ARM C++ ,"int" is not assumed where a type is missing in a declaration. Consequently:
#include<iostream>
main() { /* ... */ }
is an error because the return type of main() is missing.
Source: http://www2.research.att.com/~bs/bs_faq2.html#void-main
Because the standard says that it returns int.
Some operating systems expect an integral return value from processes. Declare main to return an int. If you don't care about the value, simply return 0.
From the comp.lang.c FAQ:
"What's the correct declaration of main?" (There are two: no args, and argc/argv.)
Can I declare main as void, to shut off these annoying ``main returns no value'' messages? (Short answer: No)
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.