Lost at C: Function Prototypes
What do you think the following C program produces?
#include <stdio.h>
void f() {
puts("here");
}
int main(void) {
f();
f(1);
f(1, 2, 3);
}
Compiling and running with gcc file.c && ./a.out
:
here here here
What is going on here?
f(void)
vs f()
In C++, f(void)
and f()
will do the same thing (in fact, using f(void)
is
frowned upon in C++). In C though, there is a semantic difference: Since our
function f
is a not a complete prototype, we are able to pass as many
arguments to it as we want.
This is normally not what you want, and can hide errors in your code. You can
enable the -Wstrict-prototypes
flag in GCC/Clang to warn on incomplete
prototypes like the one we created above.
When declaring a function that doesn't take any parameters in C, you should use
f(void)
, unless you have a good reason not to.
More Prototype Fun
Another fun thing about C is that you can drop the names of your function parameters in your function prototypes. For example:
int add(int, int);
// define "add" elsewhere
int main(void) {
return add(1, 2);
}
Since we don't define add
, we won't be able to compile it, but that's fine.
Why would this be useful you might ask?
Suppose we have 2 files, file.h
and file.c
. The .h
file will have our function
prototype, and our .c
file will have the actual definition. In this instance, we
will be specifying the parameter name(s) in both the .c
and the .h
file. What happens
when we change one of the parameter names of our function definition in the .c
file? Nothing.
Everything will compile just fine. But, the names in our function declaration (.h
file) will not
match the ones in our function definition, which could be confusing. By dropping the
name in the header file, you don't have to rename things twice.
Note: Having the parameter names in the headers is usually a good idea, especially if these are part of an API, or are user facing. Having functions that self document is hard when there are no names for the parameters.