views:

473

answers:

8

I am kind of new to C (I have prior Java, C#, and some C++ experience). In C, is it necessary to declare a function prototype or can the code compile without it? Is it good programming practice to do so? Or does it just depend on the compiler? (I am running Ubuntu 9.10 and using the GNU C Compiler, or gcc, under the Code::Blocks IDE)

+1  A: 

it's not a must, if the function is defined before its use.

Drakosha
Same in C++, of course.
anon
+2  A: 

It is not required, but it is bad practice not to use prototypes.

With prototypes, the compiler can verify you are calling the function correctly (using the right number and type of parameters).

Without prototypes, it's possible to have this:

// file1.c
void doit(double d)
{
    ....
}

int sum(int a, int b, int c)
{
    return a + b + c;
}

and this:

// file2.c

// In C, this is just a declaration and not a prototype
void doit();
int sum();

int main(int argc, char *argv[])
{
    char idea[] = "use prototypes!";

    // without the prototype, the compiler will pass a char *
    // to a function that expects a double
    doit(idea);

    // and here without a prototype the compiler allows you to
    // call a function that is expecting three argument with just
    // one argument (in the calling function, args b and c will be
    // random junk)
    return sum(argc);
}
R Samuel Klatchko
@NeilButterworth: When compiling file2.c the definition of doit (which is in file1.c) is not visible.
sepp2k
@NeilButterworth - I'll reformat, but the comments `// file1.c` and `// file2.c` are meant to imply these are different files. When compiling file2.c, the compiler will not have seen the definition in file1.c
R Samuel Klatchko
My comment preceded your edit. I'll delete it.
anon
A: 

C allows functions to be called even though they have not previously been declared, but I strongly recommend you to declare a prototype for all functions before using them so that the compiler can save you if you use the wrong arguments.

Anders Abel
A: 

You should put function declarations in the header file (X.h) and the definition in the source file (X.c). Then other files can #include "X.h" and call the function.

cpalmer
Why is this -1? This is what you should be doing.
cpalmer
Can someone explain why this is a bad idea, I was always under the impression this was standard practice? The only issue that occurs from this is circular inclusion. But, otherwise if you plan your includes you won't run into that problem.
Nathan Adams
Because not all functions are meant to be public. If you have static void foo() defined _after_ static int bar(), and bar calls foo .. well :) Why would you prototype functions that aren't exposed in a public header? I'm not the one who down voted, though.
Tim Post
I assume the downvote (not from me) was because this doesn't address the question.
anon
@Tim, bar can call foo because the compiler will already know about it from the prototype. Unless this is untrue in C, it should be true in C++. Can you post an example so maybe we can get a better idea of what you mean?@Neil Even though it doesn't answer the question directly it does relate to a "best practice" that is related to the question which I don't see as a need to down vote. Maybe not an upvote, but it isn't something that I would want removed or is unnecessary.
Nathan Adams
+3  A: 

In ANSI C, you do not have to declare a function prototype; however, it is a best practice to use them. The only reason the standard allows you to not use them is for backward compatibility with very old code.

If you do not have a prototype, and you call a function, the compiler will infer a prototype from the parameters you pass to the function. If you declare the function later in the same compilation unit, you'll get a compile error if the function's signature is different from what the compiler guessed.

Worse, if the function is in another compilation unit, there's no way to get a compilation error, since without a a prototype there's no way to check. In that case, if the compiler gets it wrong, you could get undefined behavior if the function call pushes different types on the stack than the function expects.

Convention is to always declare a prototype in a header file that has the same name as the source file containing the function.

You will not necessarily get a "compile error", if the actual function type is different from the inferred one. This is undefined behavior in C, but not a constraint violation.
AndreyT
You're right, should have been more specific, what I meant was that most compilers will throw a warning.
In C99, you do need a function declaration - though I suppose it does not have to be a prototyped declaration. C90 (C89) was a lot more lax about it. Note that you do need a prototype in scope if the function uses 'variable arguments' - even in C89/C90.
Jonathan Leffler
A: 

It's not absolutely necessary to declare a function for the calling code to compile. There are caveats though. Undeclared function is assumed to return int and compiler will issue warnings first about function being undeclared and then about any mismatches in return type and parameter types.

Having said that it's obvious that declaring functions properly with prototypes is a much better practice.

Nikolai N Fetissov
A: 

Function prototype is not mandatory according to the C99 standard.

zoli2k
+1  A: 

It is never required to declare a prototype for a function in C, neither in "old" C (including C89/90) nor in new C (C99). However, there's a significant difference between C89/90 and C99 with regard to function declarations.

In C89/90 it was not necessary to declare a function at all. If the function is not declared at the point of the call, the compiler "guesses" (infers) the declaration implicitly from the types of the arguments passed in the call and assumes that the return type is int.

For example

int main() {
  int i = foo(5); 
  /* No declaration for `foo`, no prototype for `foo`.
     Will work in C89/90. Assumes `int foo(int)` */

  return 0;
}

int foo(int i) {
  return i;
}

In C99 every function that you call must be declared before point of the call. However, it is still not necessary to declare it with a prototype specifically. A non-prototype declaration will work as well. This means that in C99 the "implicit int" rule no longer works (for inferred function return types, in this case), but parameter types can still be guessed from the argument types if function is declared without a prototype.

The previous example will not complie in C99, since foo is not declared at the point of the call. Yet, you can add a non-prototype declaration

int foo(); /* Declares `foo`, but still no prototype */

int main() {
  int i = foo(5); 
  /* No prototype for `foo`, although return type is known. 
     Will work in C99. Assumes `int foo(int)` */

  return 0;
}
...

and end up with valid C99 code.

Nevertheless, it is always a good practice to declare a prototype for the function before you call it.

An additional note: I said above that it is never required to declare a function prototype. In fact, for some functions it is a requirement. In order to properly call a variadic function in C (printf for example) the function must be declared with a prototype before the point of the call. Otherwise, the behavior is undefined. This applies to both C89/90 and C99.

AndreyT