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 ofintand with no parameters:int main(void) { /* ... */ }or with two parameters (referred to here as
argcandargv, 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 formain()but is otherwise equivalent toint main(void) { … }.In C23,
int main() { … }does provide a prototype formain()and is fully equivalent, except for spelling, toint main(void) { … }.The difference only matters if you call
main()recursively — something that is allowed in C and disallowed in C++. Withint main()in C17 or earlier, a recursive call likemain(23, "elephants");is allowed because there is no prototype specified formain()(assuming that the definition ofmain()is visible before the recursive call). Withint 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 bothint main()andint 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 recognizeint main(int argc, char **argv, char **envp)). Apple even has a fourth optional argument tomain()—int main(int argc, char **argv, char **envp, char **apple)that behaves likeargvorenvp. I need to update my answer for C23 sometime soon.