While reviewing code I came across a change set which read like this:
- void super_duper_func () {
+ void super_duper_func (void) {
I was puzzled, what’s the difference anyway except from making it explicitly clear that there are no parameter expected? Well, I was wrong. The [ISO/IEC 9899/TC2 aka ISO C99] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf) standard (read: C99 standard) states under paragraph ‘6.7.5.3 Function declarators (including prototypes)’ that
10 — The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
14 — An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the
parameters is supplied.
Therefore we can conclude that even though your code may compile and work correctly, your code is not standard compliant and you may even leap a compile time error detection. Have a look a this snippet which compiled flawless with clang 3.4:
#include
void func();
int main() {
func("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
return 0;
}
void func() {
printf("in func()\n");
}
Though when you turn on all warnings in clang you will get a warning but this is easily overlooked and not very obvious:
$ clang -std=c99 -Weverything -o empty_param_list empty_param_list.c
empty_param_list.c:10:6: warning: no previous prototype for function 'func' [-Wmissing-prototypes]
void func() {
^
empty_param_list.c:3:6: note: this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function
void func();
^
void
1 warning generated.
If you go through the code you will find a function prototype and you may think that if there was no previous prototype and the function is defined later than ‘main’ the compiler will fail anyway … In this case if you forgot the function prototype the compiler would throw an error (conflicting types for ‘func’) even if you passed no arguments.
To sum it up:
- Create function prototypes/declarations (they go before the first function definition in your source)
- If you don’t need any parameters explicitly write void in the parameter list (helps you with finding mistakes)
- Turn on all warnings with either ‘-Wall’ (gcc) or ‘-Weverything’ (clang) and don’t ignore those warnings!