Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 824
acrilige Avatar asked Oct 01 '22 11:10

acrilige


2 Answers

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.

like image 143
haccks Avatar answered Oct 11 '22 16:10

haccks


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.

like image 31
user3553031 Avatar answered Oct 11 '22 16:10

user3553031