main function with respect to C [duplicate] - c

This question already has answers here:
Non-standard signature of main() compiles successfully
(4 answers)
Closed 9 years ago.
5.1.2.2.1 Program startup
The implementation declares no prototype for this function. It shall be defined
with a return type of int and with no parameters.
I have defined like this,
int main(int a, int b, int c){.......}
It works. I didn't understood the first line "The implementation declares no prototype for this function"
Need help, Thanks

All it means is that main is not declared in advance. There's no line like
int main(int argc, char*argv[]);
and that means that when you define the function, you can pretend it takes any arguments and returns any type you like without getting a compiler error.
Of course, main is called by the operating system, so it will expect your definition to match whatever convention it uses for passing parameters. In practice, except on embedded systems, your definiton for main has to match the above.

When you are making a prototype then it means that you want to call it elsewhere which is not the case for main function.
From the docs:-
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;9) or in some other implementation-defined manner.

declaration or prototype is not require for main function
functions other than main requires declaration and
definition
int sum(int,int); //declaration
int sum(int a,int b) //definition
{
//body
}

You left out the rest of the quote from that section of the standard, I am going to quote the C99 draft standard which says:
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.
The shall be defined is the quote is the important part, it says it must follow one of these two signatures or if available some implementation specific signature which would be defined by the compiler implementor.
If I attempt to build this in the latest version of clang I see the following errors:
error: second parameter of 'main' (argument array) must be of type 'char **'
int main(int a, int b, int c){}
error: third parameter of 'main' (environment) must be of type 'char **'

Related

Is int main(void) { } a prototype?

I'm trying to understand declarations, definitions and prototypes. I came across the excellent post https://stackoverflow.com/a/41805712/1825603. I do, however, need some clarification, but because I do not have enough reputation to comment directly to the post, I will ask here...
The relevant section:
In definitions
void func1() { } // obsolescent
and
void func2(void) { }
The former declares and defines a function func1
that has no parameters and no prototype
The latter declares and defines a function func2 with a prototype that
has no parameters.
When I see int main(void) { } as one of the Standard definitions for main in C99 5.1.2.2.1, I interpret from the above that it's "a declaration and definition of a function with a prototype that has no parameters". My confusion lies with C99 5.1.2.2.1, where it says, "The implementation declares no prototype for this function." By adding the void to int main() { }, does this mean the user-level code is declaring a prototype because the implementation hasn't? And if it's not a prototype, what is the effect of adding void?
Note: I believe I understand the reason the declaration int main(void); isn't used, ie, Declare main prototype, but don't think my question is a duplicate of this.
C 2018 6.2.1 2 says:
… ((A function prototype is a declaration of a function that declares the types of its parameters.)
Thus int main(int argc, char *argv[]); is a function prototype, because it declares the types of its parameters, argc and argv.
int main(int argc, char *argv[]) {} is also a function prototype. Even thought it is a function definition, it also declares the function.
Functions can be defined with an old style that did not have declarations in the parameter list, such as:
int main(argc, argv)
int argc;
char *argv[];
{
}
Although the types of the parameters are declared in the declaration list between the function declarator and the body of the function, this is not what the C standard means by declaring the types of the parameters. This phrasing in the C standard is unfortunately imprecise, but the intent is that a “function prototype” is a declaration of the modern form with the types specified in the parameter list, contrasted with the legacy form with only the parameter names in the list.
We can see this because C 2018 6.2.7 3 distinguishes a function prototype as a function declared with a parameter type list rather than a simple identifier list:
… a function type with a parameter type list (a function prototype)…
Also note the special form (void), as in int foo(void), counts as a function prototype as a special case; it is the modern form of declaration that asserts the function has no parameters. The old form int foo(); does not specify whether the function has parameters or not.
Is int main(void) { } a prototype?
Yes.
int main(void) { } is a function declaration and definition. As a declaration, it says nothing about the parameters. As a definition, it takes no parameters: i.e void.

"Return type of main is not int" warning on macOS [duplicate]

This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 5 years ago.
So I have a MacBook Pro 2017 and whenever I compile a program that as "void main", the compiler gives me a warning saying that the return type of main is not int...
void main(){
(...)
}
Like the warning says, you should define the return type as an int:
int main() {
// bunch of code...
return 0;
}
Current versions of the C standard require that the main function has a return type of int. So you need to change the definition to int main() and have it return a value.
Section 5.1.2.2.1 of the C standard detailing hosted environments states the following:
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 or in some other implementation-defined manner.
Note that a definition of int main() is allowable as the empty parameter list means the function takes no parameters. From section 6.7.6.3:
14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator
that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator
that is not part of a definition of that function specifies that no
information about the number or types of the parameters is supplied.
Specifying the main function as void main() is a pre-standardized variant from the K&R days and is no longer valid.
It's expected that main() will return an int value. A minimal start is:
int main() {
return 0;
}
A more formal version which accepts command-line parameters:
int main(int argc, char** argv) {
return 0;
}
Declaring it with a different type makes it incompatible. Some older compilers may not care, but Xcode's does.
C has been around a long time and has evolved considerably from its early days. If you're using an older reference you may find examples with really strange notation, or conventions that are no longer value.

Isn't void in int main(void) redundant? [duplicate]

This question already has answers here:
in c: func(void) vs. func() [duplicate]
(2 answers)
Closed 7 years ago.
The C99 standard document I have clearly states that
6.7.5.3.14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
What I interpret from that sentence is that writing void in function definition is redundant. Did I get it correctly?
No, you're slightly wrong.
void specifies that there is abosolutely no arguments passed.
empty parenthesis () indicates that the function can be called with any number of arguments, without generating a warning.
Note: Remember, there is no prototype defined or supplied by the implementation for main().
Maybe, C11 standard, chapter 5.1.2.2.1, describes it better way,
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.

main() function with wrong signature gets called

The standard says:
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; 10) or in some other
implementation-defined manner.
If I write this:
#include <stdio.h>
struct some_struct
{
int i;
};
float main(struct some_struct s)
{
printf("Why does this main get called?\n");
}
Actually, it gets called with any prototype, as I see, and there is no any runtime error.
Why isn't it forbidden? Are there no reasons for that? Also, how does it get called if the signature is wrong?
I've used gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Starting with standard conformance:
1 In this International Standard, ‘‘shall’’ is to be interpreted as a requirement on an implementation or on a program; conversely, ‘‘shall not’’ is to be interpreted as a prohibition.
2 If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or run time constraint is violated, the behavior is undefined. [...]
Look at the emphasis on the paragraph you quoted:
[...]. It shall be defined with a return type of int and with [...]
In the case,
float main(struct some_struct s){...}
"shall" requirement is outside of constraint because standard clearly states that main return type shall be int either with no parameters
int main(void) { /* ... */ }
or with two parameters
int main(int argc, char argv[]) { / ... */ }
This means that behavior of your program is undefined.
Your quote from the standard states that "some other implementation-defined manner". It appears that gcc is quite liberal in what it allows as signatures for main; it seems to ignore the parameter that you're passing. If you compile with gcc -Wall, you get warnings about main's prototype not being what it expects.
clang is less permissive about main's prototype. It will accept the return type of float with a warning, but will error out on the struct argument.
C looks up functions by name only, so the linker doesn't care about the unusual return type and parameters.
In C, if a function signature doesn’t specify any argument, it means that the function can be called with any number of parameters or without any parameters.
Hey checkout out this link - https://www.geeksforgeeks.org/difference-int-main-int-mainvoid/

Difference between int main() and int main(void)?

What does the following mean :
int main(void) {...}
VS
int main() {...}
?
I think that int main() {...} means that main doesn't receive any parameters (from command line) , however:
int main(int argc, char *argv[])
does.
But, what does int main(void) {...} mean? And, what does void stand for ?
I've looked here but it's somehow a different question .
In C++, there is no difference.
In C, the difference is questionable. Some love to argue that the latter version (the one without void) is technically just a common implementation extension and not guaranteed to work by the standard because of the wording in the standard. However, the standard clearly states that in a function definition an empty set of parameters has a well-defined behaviour: that the function does not take any parameters. Thus such a definition for main matches the following description in the standard:
It [main] shall be defined with a return type of int and with no parameters.
There is, however, a noticeable difference between the two: namely, the version without void fails to provide a correct prototype for the function:
// this is OK.
int main()
{
if (0) main(42);
}
// this requires a diagnostic to be shown during compiling
int main(void)
{
if (0) main(42);
}
Oh, and just to be complete: the void has the following meaning in all function declarators:
(6.7.6.3p10) The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
First of all, there is a difference of what is allowed for hosted systems and freestanding systems, as shown here.
For hosted systems, 5.1.2.2.1 Program startup applies:
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)
... (more text follows regarding argv/argc etc styles).
The interesting part is "with no parameters". int main() and int main (void) are currently equivalent, since they are both function declarators and have no parameters. The following applies (6.7.6.3 ):
10 The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
/--/
14 An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied.145)
Emphasis mine, the bold text is what applies to int main(). There is also note 145) at the end of the text, which says "See ‘‘future language directions’’ (6.11.6)":
6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
And here is the difference. Being a function declarator, int main() is bad style because of the above, since it is not guaranteed to work in the next version of the C standard. It is flagged as an obsolescent feature in C11.
You should therefore always use int main (void) on a hosted system and never int main(), even if the two forms are, for now, equivalent.
In C++ both forms are completely equivalent, but there int main() is the preferred style for subjective, cosmetic reasons (Bjarne Stroustrup says so... which is probably quite a bad rationale for explaining why you do something in a particular way).
In C, in a prototype (not in C++ though) an empty argument list means that the function could take any arguments (in the definition of a function, it means no arguments). In C++, an empty parameter list means no arguments. In C, to get no arguments, you have to use void. See this question for a better explanation.
In C++ having a function foo(void) and foo() is the same thing. However, in C it's different: foo(void) is a function that has no arguments, while foo() is a function with unspecified arguments.
In C++, there is no difference, both are same.
Both definitions work in C also, but the second definition with void is considered technically better as it clearly specifies that main can only be called without any parameter.
In C, if a function signature doesn’t specify any argument, it means that the function can be called with any number of parameters or without any parameters. For example, try to compile and run following two C programs (remember to save your files as .c).
In C++, there is no difference between the two, and int main() is a legal signature and return type for main.
I know the thread is old but this question was bothering me for a while a few years ago so I wanted to throw in my half a cent(if that).
I always treat C functions as if they have fixed amount of arguments regardless of context, unless they use va_args. That is, I trust main to ALWAYS have the prototype:
int main(int argc, char **argv).
even if no arguments are passed, the function has these arguments on the stack because the main function does not have function overloading.
C does have the ability to have primitive overloading through just pretending the argument is not there. In which case, the argument is still passed and is on the stack but you never access it, so it merely reduces size of the source code.
Saying int main() simply means that I know that the function may have parameters, but I am not using them, so I write int main().
Saying int main(void) says that main CERTAINLY has no arguments, and implies that there are two different function prototypes:
int main(void);
int main(int argc, char **argv);
Since C has no function overloading, this is somewhat misleading to me, and I distrust code that has main(void) in it. I would not if main NEVER took any parameters, in which case main(void) would be completely OK.
NOTE: In some implementations, there are more parameters in main than argc and argv, such as env, but this does not bother me because I know that I do not explicitly say that those are the only two parameters, but those are the minimal parameters and it's okay to have more, but not less. This is in contrast to downright saying int main(void) which yells at me as THIS FUNCTION HAS NO PARAMETERS, which isn't true, since it does, they are just omitted.
Here is my basis code:
/* sample.c - build into sample. */
#include <stdio.h>
int main(void)
{
int _argc = *((int *)2686800);
char ***_pargv = (char ***)2686804;
int i;
for (i = 1; i < _argc; ++i) {
printf("%s ", (*_pargv)[i]);
}
return 0;
}
./sample I clearly have arguments
The function clearly has arguments passed to it, despite going out of the way to explicitly say that it doesn't by typing void into the function prototype.
As eq- says above:
(6.7.6.3p10) The special case of an unnamed parameter of type void as the
only item in the list specifies that the function has no parameters.
Thus saying that the function has void as an argument but actually having arguments on the stack is a contradiction.
My point is that arguments are still there, so explicitly asserting that main is void of arguments is dishonest. The honest way would be to say int main(), which claims nothing about how many parameters it has, only how many parameters you are care about.
NOTE2: The _argc, _pargv are system dependent, to find your values you must find them out by running this program:
/* findargs.c */
#include <stdio.h>
int main(int argc, char **argv)
{
printf("address of argc is %u.\n", &argc);
printf("address of argv is %u.\n", &argv);
return 0;
}
These values should remain correct for your specific system.
In C++, there is no difference between int main() and int main(void).
But in C they are little bit different.
int main() indicates that the main function can be called with any number of parameters or without any parameter. On the other hand, int main(void) indicates that the main function will be called without any parameter
#include <stdio.h>
int main()
{
static int i = 5;
if (--i){
printf("%d ", i);
main(10);
}
}
Output: 4 3 2 1
#include <stdio.h>
int main(void)
{
static int i = 5;
if (--i){
printf("%d ", i);
main(10);
}
}
It will show error. Because, in int main(void) parameter is void but in the program we have taken main(10) (which defines some value, not void)
Technically, if your host is partially POSIX compliant, then you have
int main(); // this legacy is always used by the run time library
int main(int argc); // illegal by compiler
int main(int argc, char** argv); // required by C standards
int main(int argc, char** argv, char** envp); // required by POSIX standard
If you have a Mac, there is also this
int main(int argc, char** argv, char** envp, char** apple); // required by Macintosh standard
Your host will send all the arguments, so a host will always send argc, argv, and envp (and apple if you are using an Apple product), but the programmer could have their main declared as taking void. The implicit function pointer typecast is technically an undefined behavior.
To prevent the typecast undefined behavior, int main() is a neutral form that means it could take any fixed number of arguments using canonical type promotion (int or larger, and double or larger) and int main(int argc, ...) means it could take any variable number of arguments also with canonical type promotion. In other words, the form return_type function_name() is an exception to undefined behavior.
In C++:
ㅤㅤint main() and int main(void) are the same in C++. They both take 0 and only 0 parameters.
In C:
ㅤㅤint main() takes as many arguments as you want. The function just won't use them. intㅤㅤㅤ main(void) makes it so passing an argument will create an error and make it impossible to ㅤㅤpass arguments.
ㅤ

Resources