main() function with wrong signature gets called - c

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/

Related

A function without parameters in C

I know that “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„[1]:
// No information about the parameters is supplied.
int foo();
I know that “an empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters„[2].
// In this case the foo() function has no parameters.
int foo()
{
// ...
}
I know that “the special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters„[3]:
// foo() has no parameters.
int foo(void);
// bar() has no parameters.
int bar(void)
{
// ...
};
So here are some questions:
Is int main() { /* ... */ } legal? The standard states[4] that
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.
So, is int main() { /* ... */ } is equivalent to int main(void) { /*... */ }?
Why GCC allows pass parameters to a function that has no parameters?
int foo();
int bar()
{
return 42;
}
int main(void)
{
// Should be OK.
foo(13);
// Should give a compile-time error.
bar(1, 12);
}
But I actually can compile the program with gcc version 10.1.0 (GCC): gcc -std=c17 -Werror -c test.c.
I've read some related questions, such as What are the valid signatures for C's main() function?, but they do not take into account the following standard clause[2]:
An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters.
So, is my understanding of this clause correct?
ISO/IEC 9899:2017 § 6.7.6.3 / 14.
ISO/IEC 9899:2017 § 6.7.6.3 / 14.
ISO/IEC 9899:2017 § 6.7.6.3 / 10.
ISO/IEC 9899:2017 § 5.1.2.2.1 / 1.
Per the letter of the standard, yes. 5.1.2.2.1 says "[main] shall be defined with a return type of int[,] and with no parameters, or with two parameters [...]". int main() {} is a definition with return type int and no parameters, and 5.1.2.2.1 does not say anywhere that the definition is required to be prototyped.
(The code fragment shown immediately after "and with no parameters" may appear to be making a requirement to write (void), but all code fragments are considered to be examples, and therefore non-normative. It doesn't actually say this anywhere in the text, but it has come up in DR responses at least a couple times; I regret I do not remember specific numbers, it was more than 15 years ago now.)
However, because of (2), you should write int main(void) anyway.
Section 6.5.2.2 (semantics of function calls), paragraph 8, says "the number and types of arguments are not compared with those of the parameters in a function definition that does not include a function prototype declarator." However, paragraph 6 of the same section says that in the event of an actual mismatch between the definition and the callsite the behavior is undefined. That means, compilers are allowed to issue an error when a function defined as T foo() {} is called with arguments, but it also means they are allowed not to issue an error.
For the sake of backward compatibility with pre-C89 code, which regularly did make function calls with a mismatched number of arguments, many compilers will accept such code without complaint. I have seen this behavior with Clang and MSVC as well as GCC. Newer versions of Clang do give you a warning:
$ clang --version | head -1
clang version 9.0.1-13
$ clang test.c
test.c:14:14: warning: too many arguments in call to 'bar'
bar(1, 12);
~~~ ^
I don't know how long this warning's been on by default.
Someone ought to go through all of GCC's intentional leniences for the sake of backward compatibility with really old code, and turn many of them off by default, but nobody's interested in funding this so it probably won't ever happen.
This standard is vague on this. It does not really define what "or equivalent" means. However you may want to know that the standard uses int main() in at least one code example. Code examples are not normative though.
The call site doesn't see a definition. It only sees a declaration. The (draft document N2176) standard says
[6.9.1/7] If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit.
A declarator without a parameter type list does not serve as a function prototype for later calls, even if it is a part of a definition.
[6.5.2.2/8] the number and types of arguments are
not compared with those of the parameters in a function definition that does not include a function prototype declarator.

Is int main() { } (without "void") valid and portable in ISO C?

The C standard specifies two forms of definition for main for a
hosted implementation:
int main(void) { /* ... */ }
and
int main(int argc, char *argv[]) { /* ... */ }
It may be defined in ways that are "equivalent" to the above (for
example, you can change the parameter names, replace int by a typedef
name defined as int, or write char *argv[] as char **argv).
It may also be defined "in some other implementation-defined manner"
-- which means that things like int main(int argc, char *argv[],
char *envp) are valid if the implementation documents them.
The "in some other implementation-defined manner" clause was not in
the 1989/1990 standard; it was added by the 1999 standard (but the
earlier standard permitted extensions, so an implementation could
still permit other forms).
My question is this: Given the current (2011) ISO C standard, is a
definition of the form
int main() { /* ... */ }
valid and portable for all hosted implementations?
(Note that I am not addressing either void main or the use of
int main() without parentheses in C++. This is just about the
distinction between int main(void) and int main() in ISO C.)
No.
According to the normative wording of the standard, a definition
using empty parentheses without the void keyword is not one of the
forms that must be accepted, and strictly speaking the behavior of
such a program is undefined.
Reference:
N1570
section 5.1.2.2.1. (The published 2011 ISO C standard, which is not
freely available, has the same wording as the N1570 draft.)
Paragraph 1 says:
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.
The use of the word "shall" outside a constraint means that any
program that violates it has undefined behavior. So if, for example, I write:
double main(unsigned long ocelots) { return ocelots / 3.14159; }
a conforming compiler isn't required to print a diagnostic, but it's
also not required either to compile the program or, if it does compile
it, to have it behave in any particular manner.
If int main() were equivalent to int main(void), then it
would be valid and portable to any conforming hosted implementation.
But it's not equivalent.
int main(void) { }
provides both a declaration (in this case, a prototype) and a
definition. The declaration, by using the void keyword, specifies that the function has no parameters. The definition specifies the same thing.
If I instead write:
int main() { }
then I'm using an old-style declaration and definition. (Such
declarations and definitions are obsolescent, but they're still
part of the language definition, and all conforming compilers must
still support them.)
As a declaration, it doesn't specify the number or type(s) of arguments
expected by the function. As a definition, it defines no parameters,
but compilers needn't use that information to diagnose incorrect calls.
DR #317 includes the C standard committee's 2006 ruling that a definition with () does not provide a prototype equivalent to one with (void) (thanks to hvd for finding that reference).
C allows main to be called recursively. Suppose I write:
int main(void) {
if (0) {
main(42);
}
}
The visible prototype int main(void) specifies that main takes
no arguments. A call that attempts to pass one or more arguments
violates a constraint, requiring a compile-time diagnostic.
Or suppose I write:
int main() {
if (0) {
main(42);
}
}
If the call main(42) were executed, it would have undefined behavior
-- but it doesn't violate a constraint, and no diagnostic is required.
Since it's protected by if (0), the call never happens, and
the undefined behavior never actually occurs. If we assume that
int main() is valid, then this program must be accepted by any
conforming compiler. But because of that, it demonstrates that
int main() is not equivalent to int main(void), and therefore
is not covered by 5.1.2.2.1.
Conclusion: Following the wording of the standard, an
implementation is permitted to document that int main() { } is
permitted. If it doesn't document it, it's still permitted to accept
it without complaint. But a conforming compiler may also reject
int main() { }, because it is not one of the forms permitted by
the standard, and its behavior is therefore undefined.
But there's still an open question: Was that the intent of the authors
of the standard?
Prior to the publication of the 1989 ANSI C standard, the void
keyword did not exist. Pre-ANSI (K&R) C programs would define main
either as
main()
or as
int main()
A major goal of the ANSI standard was to add new features (including
prototypes) without breaking existing pre-ANSI code. Stating that
int main() is no longer valid would have violated that goal.
My suspicion is that the authors of the C standard did not intend
to make int main() invalid. But the standard as written does not
reflect that intent; it at least permits a conforming C compiler
to reject int main().
Practically speaking, you can almost certainly get away with it.
Every C compiler I've ever tried will accept
int main() { return 0; }
without complaint, with behavior equivalent to
int main(void) { return 0; }
But for a variety of reasons:
Following both the letter and the intent of the standard;
Avoiding the use of an obsolescent feature (a future standard could remove old-style function definitions);
Maintaining good coding habits (the difference between () and (void) is important for functions other than main that are actually called by other functions).
I recommend always writing int main(void) rather than int main().
It states the intent more clearly, and you can be 100% sure that your
compiler will accept it, rather than 99.9%.
A strong indication that int main() is meant to be valid, regardless of whether the standard accurately gives the wording to make it valid, is the fact that int main() is occasionally used in the standard without anyone raising any objection. While examples are not normative, they do indicate intent.
6.5.3.4 The sizeof and _Alignof operators
8 EXAMPLE 3 In this example, the size of a variable length array is computed and returned from a function:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}
6.7.6.3 Function declarators (including prototypes)
20 EXAMPLE 4 The following prototype has a variably modified parameter.
void addscalar(int n, int m,
double a[n][n*m+300], double x);
int main()
{
double b[4][308];
addscalar(4, 2, b, 2.17);
return 0;
}
void addscalar(int n, int m,
double a[n][n*m+300], double x)
{
for (int i = 0; i < n; i++)
for (int j = 0, k = n*m+300; j < k; j++)
// a is a pointer to a VLA with n*m+300 elements
a[i][j] += x;
}
As for the actual normative text of the standard, I think too much is being read into "equivalent". It should be pretty clear that
int main (int argc, char *argv[]) {
(void) argc; (void) argv;
return 0;
}
is valid, and that
int main (int x, char *y[]) {
(void) argc; (void) argv;
return 0;
}
is invalid. Nonetheless, the standard explicitly states in the normative text that any names may be used, meaning that int main (int argc, char *argv[]) and int main (int x, char *y[]) count as equivalent for the purposes of 5.1.2.2.1. The strict English meaning of the word "equivalent" is not how it is meant to be read.
A somewhat looser interpretation of the word is what Keith Thompson suggests in his answer.
An equally valid even looser interpretation of the word does allow int main(): both int main(void) and int main() define main as a function returning int and taking no parameters.
Neither the standard nor any official DRs currently answer the question of which interpretation is intended, so the question is unanswerable, but the examples strongly suggest that last interpretation.
Yes.
int main() { /* ... */ }
is equivalent to
int main(void) { /* ... */ }
N1570 5.1.2.2.1/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.
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.
(emphasis mine)
As is clearly stated by the standard, the definition int main() { /* ... */ } does specify that the funtion main has no parameters. And it is clear to all of us, that this function definition does specify that the return type of the function main is int. And, since 5.1.2.2.1 does not require the declaration of main to have a prototype, we can safely affirm that the definition int main() { /* ... */ } satisfies all the requirement imposed by the standard (It [the main funtion] shall be defined with a return type of int and with no parameters, or [some other forms] .).
Nonetheless you should never use int main() {} in your code, because "The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature." (6.11.6), and because this form of definition does not include a function prototype declarator, the compiler won't check whether the number and types of arguments are correct.
N1570 6.5.2.2/8
No other conversions are performed implicitly; in particular, the number and types of
arguments are not compared with those of the parameters in a function definition that
does not include a function prototype declarator.
(emphasis mine)

main function with respect to C [duplicate]

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 **'

main() function defined without return type gives warning

This is my program:
main()
{
printf("hello world\n");
}
I get this warning when compiling it:
function should return a value
When changing main() to void main(), the warning disappears.
Why is that so?
There are few things which you should take note of :
The int is the main() function's return type. That means that the kind of value main() can
return is an integer.
main( ) was tolerated by the C90 compilers but not by C99 compilers which means its not a part of C99 standard anymore , so don't do this.
void main() is not a standard form ,some compilers allow this, but none of the standards have ever listed it as an option. Therefore,
compilers don't have to accept this form, and several don't. Again, stick to the standard form,
and you won't run into problems if you move a program from one compiler to another.
And one last thing , instead of writing main like this :
int main() // here you are being silent about passing arguments to main , meaning it may or may not take arguments
write like this :
int main(void)// this specifies there are no arguments taken by main
You might wanna look at the C99 standard for further details.
Quick summary: If you don't want to use command-line arguments, you should write:
int main(void) {
/* body of main function */
}
If you do:
int main(int argc, char *argv[]) {
/* ... */
}
These are the only portable ways to define the main function.
You should probably have a return 0; at the end, though it's not strictly necessary. Returning 0 indicates successful execution. There are ways to indicate that execution failed; I won't get into that here.
There's some history behind this. The rules for a valid definition of the main function have changed a bit across different releases of the C standard.
Before the introduction of the first official standard for C in 1989, the most common form was:
main()
{
/* ... */
}
Or, if you wanted to use command-line arguments:
main(argc, argv)
/* argc is implicitly of type int */
char *argv[];
{
/* ... */
}
There was no way to define a function that didn't return a value. If you didn't specify a return type, it defaulted to int.
The 1989 ANSI C standard (which was republished with editorial changes as the 1990 ISO C standard) introduced prototypes, function declarations and definitions that specify the parameter types. There are two equally valid definitions for main. You can use one or the other depending on whether you need to use command line arguments:
int main(void) {
/* ... */
}
or
int main(int argc, char *argv[]) {
/* ... */
}
(char *argv[] can also be written as char **argv. This rule applies only to parameter definitions.)
A given compiler may or may not choose to permit other forms. For example, some compilers support a third parameter envp.
Somehow, some authors have gotten the idea that void main() or void main(void) is valid. It can be valid for some particular compiler, but only if that compiler explicitly supports it. It's not portable. The odd thing about this is that the same standard that first introduced the void keyword simultaneously established the rule that main's return type is int.
void main() is useful as an indicator that the author of the book you're reading doesn't know the C language very well, and that you should find another book.
The story is different for "freestanding" (embedded) systems. For such systems, the program's entry point is entirely implementation-defined, and might not even be called main. Defining it as void main(void) may well be valid for such systems.
The 1999 ISO C standard dropped the "implicit int" rule. Taking advantage of that rule was probably never a good idea in the first place. As of ISO C 1990, you could legally use:
main(void) { /* ... */ }
because it was equivalent to:
int main(void) { /* ... */ }
As of the 1999 standard, the int is mandatory.
The 1999 standard also added a special-case rule: reaching the closing } of the main function is equivalent to executing return 0;. It's still not a bad idea to add the explicit return 0;, especially if your code might be compiled with a pre-C99 compiler.
The 2011 ISO C standard didn't make any changes in this area.
The difference between int main() and int main(void) is that the latter explicitly says that main takes no arguments; the former doesn't specify how many arguments it takes. Use the int main(void) form. There have been debates about whether int main() is even legal.
You can likely get away with writing void main(), since it's an error that compilers are not actually required to diagnose (it's undefined behavior unless the implementation documents it).
The bottom line: The proper definition of main has a long and varied history, and there are a lot of variant forms you can probably get away with using. But unless you're programming for an embedded system, there is no point in using anything other than one of the two officially valid forms:
int main(void) { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }
c automatically implies the datatype int to functions with no declared datatype. So as far as the compiler is concerned the above is:
int main()
{
printf("hello world\n");
}
This expects that you would return an integer at the end of it with a return statement. If you explicitly specify it as void main() you are telling the compiler that the function does not have a return value, hence no warning.
The reason that this is not an error is that if not specified, main() will return 0; at the end of execution. However the compiler is still giving you a warning that this is happening.
Best practice is to use int main() and then return 0 at the end of your program execution like this.
int main()
{
printf("hello world\n");
return 0;
}
See: this question for more information.
You got the warning because you didn't specify the return type of main.
You should always use int main, and return an int number, usually 0 for success.
int main()
{
printf("hello world\n");
return 0; //you can omit this since C99
}
Using void main on a hosted environment(normally we are, if not, the following doesn't have to be true) leads to undefined behavior, even though it works in some compilers, never use it.
The standard says main has two kinds of prototype, both returns int:
C11 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.
write
return 0 ;
at the last line.

Is this code valid under any C standard?

Does this code follow C standards (e.g. C89, C99, C10x)?
void
main(int a,int b, int c, int d,char *msg){
if(d==1){
printf("%s\n",msg);
}else{
main(1,2,3,1,&"Hello Stackoverflow");
}
}
If not, why?
There's one error: &"Hello Stackoverflow" does not have type char*, so you shouldn't pass that to a function expecting that type.
Apart from that, this program is allowed by the Standard as an implementation-specific extension, but a compiler has the freedom to decline it.
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.
(2011 Standard, latest draft section 5.1.2.2.1, emphasis added.)
There is no ban on recursive calls to main in the C Standard. This is a difference with C++, which does outlaw that.
You mean beside it won't run? main is defined to take int, char** as arguments.
Depending on the compiler, this either will fail to start up as the run-time can't find main(int, char**), or on older compilers it'll just crash because it piddles on the stack.
It's only valid under C99 and later if the implementation explicitly documents that main may take 5 parameters (4 int and 1 char *) and return void (that's the "or in some other implementation-defined manner" clause that larsmans referenced in his now-un-deleted answer, and I don't think that clause was present in C89).
Otherwise the behavior is undefined, meaning the compiler may or may not choke on it.

Resources