From ISO/IEC 9899:2024, 5.1.2.3.2, 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;6) or in some other implementation-defined manner.
And a footnote at the end of the page says:
- Thus,
int
can be replaced by a typedef name defined asint
, or the type ofargv
can be written aschar ** argv
, or the return type may be specified bytypeof(1)
, and so on.
From this, I conclude that the prototype for main()
can be any of the following:
1. int main(void) { /* ... */ }
/* Because function declarations whose parameter list is empty is treated the same
as a parameter list that contains only a single void in C23. */
2. int main() { /* ... */ }
3. int main(int argc, char *argv[]) { /* ... */ }
4. int main(int argc, char **argv) { /* ... */ }
/* Or any other value than 1 that fits in the range of an int. */
5. typeof(1) main() { /* ... */ } /* And all the other aforementioned variants as well. */
6. typedef int val;
val main(val argc, char **argv) { /* ... */ } /* And all the other aforementioned variants as well. */
Are there any other types that are equivalent? @Davislor at codereview.stackexchange.com says that (in the comments):
And 6.7.6.3 says that, in a function declaration,
*argv[]
andconst **argv
are “compatible types.”
6.7.6.3 is too dense for me to make sense of. Is the following:
7. int main(int argc, char const **argv) { /* ... */ }
a valid prototype for main()
? If so, what about:
int main(const int argc, char **const argv) { /* ... */ }
int main(int argc, char **const volatile _Atomic argv) { /* ... */ }
And other compatible types, if any?
*argv[]
andconst **argv
are compatible types. What it does say means that parameter declarations ofT *argv[]
,T *argv[const]
, andT ** const argv
would be taken as the same when considering function compatibility. Note that the qualifier on the parameter directly is removed when considering compatibility, not the qualifier on what the parameter points to or any further levels of indirection. Your link is just to codereview.stackexchange.com, not to the place where @Davislor made this statement. You should give a full URL to it so it can be corrected.const
object is not modified, the memory of avolatile
object must be accessed each time, and so on…const
is exactly the same as passing an argument to a function that treats its parameter as non-const
.