5

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

acrilige
  • 2,436
  • 20
  • 30
  • 5
    Compile with `-Wall -Werror`or `-pedantic-errors` and you'll see it is not allowed. – ouah Jun 28 '14 at 09:13
  • Basically, if main() isn't typed, it defaults to int, if it is typed and not to an int -- it is an error. – David C. Rankin Jun 28 '14 at 09:15
  • Understood about compile flags, but how does it get called then? It just looks up for the function with name "main" and ignores any arguments? – acrilige Jun 28 '14 at 09:18
  • The linker in C only looks at function names. Including the arguments in the linkage is a C++ feature, required to support function overloads. Well known as "name mangling". – Hans Passant Jun 28 '14 at 09:19
  • I've got it. Thanks. Might write an answer so that I could accept it – acrilige Jun 28 '14 at 09:21
  • argc and argv are pushed on the stack, main is called. All is well until you try to access the passed arguments. – Tarik Jun 28 '14 at 09:34

3 Answers3

3

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.

the busybee
  • 10,755
  • 3
  • 13
  • 30
haccks
  • 104,019
  • 25
  • 176
  • 264
  • so, `main() { ... }` is undefined behaviour? I've seen it a lot – acrilige Jun 30 '14 at 12:21
  • 1
    Allowed in C89. C99 and latter deprecated this signature. – haccks Jun 30 '14 at 12:32
  • We can also see main with a third parameter : environment variables. cf. https://stackoverflow.com/a/10321474/14393739 – Rachid K. Jan 08 '21 at 14:42
  • 1
    This answer omits part of the text of the passage it quotes. Per C 2018 5.1.2.2.1, `main` may be defined “… or in some other implementation-defined manner.” – Eric Postpischil Jan 08 '21 at 14:49
  • There might be some question in 5.1.2.2.1 1 about whether the sentence structure makes that “or” apply to just the parameters or to the return type as well. However, 5.1.2.2.3 1 makes it clear the standard makes provision for other return types: “If the return type of the `main` function is a type compatible with `int`,… If the return type is not compatible with `int`,…” – Eric Postpischil Jan 08 '21 at 15:00
2

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.

user3553031
  • 5,990
  • 1
  • 20
  • 40
  • That's odd of Clang. It feels the wrong way round. It should be a proper error to not have return type `int` (since there's no possible well-formed program that *also* has a `float main(...)`, since `main` must not be overloaded). However, implementations are free to support any kind of parameters for `main`, so it would be OK to say "your signature is ignored" or so and still be conforming. – Kerrek SB Jun 28 '14 at 11:05
  • “Implementation-defined” means the implementation **defines** it, that is, it states it in documentation. The fact that a program seems to “work” when compiled with GCC and executed does not mean the behavior is implementation-defined. – Eric Postpischil Jan 08 '21 at 14:29
  • @KerrekSB: The C standard allows implementations to support return types other than `int` for `main`; C 2018 5.1.2.2.1 says `main` shall be defined “… or in some other implementation-defined manner.” However, I do not think that is what Clang is doing here. Rather, the requirements on the declaration of `main` are not constraints, and the C standard does not require a compiler to refuse to translate a program because of them. As C 2018 note 9 says, “… [An implementation] can also successfully translate an invalid program…” – Eric Postpischil Jan 08 '21 at 14:47
  • @KerrekSB: Note also 5.1.2.2.3 1: “If the return type of the `main` function is a type compatible with `int`,…” So the standard clearly makes provision for other return types for `main`. – Eric Postpischil Jan 08 '21 at 14:57
-1

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/

DevesH
  • 486
  • 4
  • 18