C23 introduced new semantics in function declarators:
6.7.6.3 Function declarators
[...]
13 For a function declarator without a parameter type list: the effect is as if it were declared with a parameter type list consisting of the keyword
void
. A function declarator provides a prototype for the function.
This seems to imply that a function definition with an empty parameter list can be written equivalently with ()
or (void)
.
Yet this equivalence does not seem guaranteed for the main
function:
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 ofint
and with no parameters:int main(void) { /* ... */ }
or with two parameters (referred to here as
argc
andargv
, 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.
This does not seem to guarantee that int main() { /* ... */ }
is a valid definition for main
, or does equivalent cover this variant?
It troubles me that the 2 examples in C17 that use the syntax int main()
(in 6.5.3.4 and 6.7.6.3) have been changed to use int main(void)
in the latest C23 draft.
In C17 and earlier versions of the standard, int main() { … }
does not provide a prototype for main()
but is otherwise equivalent to int main(void) { … }
.
In C23, int main() { … }
does provide a prototype for main()
and is fully equivalent, except for spelling, to int main(void) { … }
.
The difference only matters if you call main()
recursively — something that is allowed in C and disallowed in C++. With int main()
in C17 or earlier, a recursive call like main(23, "elephants");
is allowed because there is no prototype specified for main()
(assuming that the definition of main()
is visible before the recursive call). With int main(void)
, that is not allowed because there is a prototype in scope that says "no arguments".
Note what is said in What should main()
return in C and C++? That has extensive discussions, including that the C17 and earlier standards use both int main()
and int main(void)
in their (non-normative) examples. It also points out what Microsoft specifies for Windows systems and what Annex J "Common Extensions" mentions (both recognize int main(int argc, char **argv, char **envp)
). Apple even has a fourth optional argument to main()
— int main(int argc, char **argv, char **envp, char **apple)
that behaves like argv
or envp
. I need to update my answer for C23 sometime soon.
All code fragments in the standard are considered to be examples, and, therefore, non-normative.
The normative requirement is what the text says: "[main] shall be defined with a return type of int and with no parameters[, or ...]". In C2023, int main() { ... }
defines main
with a return type of int and with no parameters, so it meets the requirement.
As pointed out in the comments on the question, C2011 had language that meant a definition int main() { ... }
would have, under that standard, defined main
with a return type of int and with no parameters, although a declaration int main();
would not have declared main
with no parameters. I cannot conveniently check C1999 or earlier from this computer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With