int f(void);
declares f
as a function taking no arguments and returning an int
result, whereas
int f();
declares f
as a function taking a fixed but unspecified number and type of arguments (and, of course, returning an int
result).
Given such a declaration, there has to be a definition somewhere that actually defines the parameters. If it takes no parameters, it might be defined as:
int f() {
return 42;
};
If it takes 2 int
parameters, it might be defined as:
int f(int x, int y) {
return x + y;
}
Either definition is compatible with int f();
, but only the first is compatible with int f(void)
.
A function declaration that specifies the type(s) of the parameters, or, as a special case, uses the void
keyword to specify that there are no parameters, is a prototype. A function declaration that doesn't do this, such as int f();
is an old-style declaration.
Unless you're stuck using a decades-old pre-ANSI compiler that doesn't support prototypes, or you're maintaining very old code and don't have the time or other resources to update it, there is no reason not to use prototypes. If you call a function with no visible prototype, you still have to pass the correct number and type(s) of arguments; the difference is that the compiler will be unable to tell you if the call is incorrect.
(You can define a function that takes a variable number and type of arguments; printf
is an example of this. This is done using the , ...
notation. The function itself uses features defined in <stdarg.h>
to process the arguments. But that has nothing to do with the declarations shown in your question.)
Here's a small program using obsolescent old-style function declarations and definitions:
#include <stdio.h>
#include <stdlib.h>
int add();
int main(argc, argv)
int argc;
char **argv;
{
if (argc == 3) {
/* NOTE: atoi() does no error checking */
printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
}
else {
fprintf(stderr, "Usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
}
int add(x, y)
int x, y;
{
return x + y;
}
Note that if I had written add(1, 2, 3, 4)
or add("foo", "bar")
, the compiler wouldn't have caught the error; the program just would have misbehaved.
Here's an equivalent program using modern function declarations and definitions:
#include <stdio.h>
#include <stdlib.h>
int add(int x, int y);
int main(int argc, char **argv) {
if (argc == 3) {
/* NOTE: atoi() does no error checking */
printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
}
else {
fprintf(stderr, "Usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
}
int add(int x, int y) {
return x + y;
}
The visible prototype means that the compiler is able to diagnose incorrect calls.