(I would take out the word "main" here: I have no idea what it is
doing in this sentence. I would say that "good form has prototypes
for functions before calls to those functions." It is also
generally wise to have those same prototypes appear before the
definition of the function as well, in more complicated situations
involving header files and separate compilation.)
Yes. Note in particular that even a function that has no arguments
at all -- such as:
void print_header(void) {
puts("==== header ====");
}
for instance -- needs to have the "void" keyword in a prototype:
void print_header(void); /* prototype */
because writing this:
void print_header(); /* not a prototype! */
gives you a declaration, but not a prototype. (This is a historical
oddity having to do with adding prototypes in 1989, where C had
none before that. The ANSI committee folks decided not to change
the meaning of "old style" declarations, so they had to invent new
syntax: "the absence of arguments here means nothing about the
arguments; the presence of a `void' keyword means there are no
arguments".)
No -- but it is often a good idea to have them match, even to the
very whitespace.
The part(s) of the prototype arguments that matter *to the compiler*
are the number and type of arguments:
void fA(void); /* zero arguments */
void fB(int, char *); /* two arguments: int, pointer-to-char */
void fC(double); /* one argument: double */
but the rest is useful to humans:
void do_some_operation(char *output, char *input, int operation);
void do_other_operation(char *input, int operation, char *output);
Here the compiler cares only that there are three arguments, two
of type "pointer to char" and one of type "int", but a person
writing code probably wants to know which "char *" is the "output"
and which one is the "input".
We could leave out the name "operation",
because there is only one "int", and if an operation has to be an
int, it is immediately obvious which of the one (count them 1)
"int" parameters is the "int" parameter.
Of course, "good design" would also suggest that all of the
various "do an operation" functions take their input, output,
and operation parameters in the same places -- but having the
names, too, is a good thing.
Note that those who intentionally obfuscate their code (perhaps
in an attempt to obtain job security) might name their parameters
in a deliberately-confusing way:
void do_third_operation(char *kumquat, int output, char *lemon);
While the computer does not care, I will say that *I* care, and
would complain quite a bit about such code.