I'm studying C and my book is explaining how to "prototype a function" so we can use it before we define it.
The point is that I can't imagine a situation in which is needed to use a function before have defined it, why can't we just define it at the beginning?
Can you please provide an example in which is strictly necessary to prototype a function (if it exists)?
One use-case is when you want to take a function pointer to a function defined in another source file. (Or hand-written in asm). Taking a function-pointer always requires the function to be declared ahead of time, either by a definition or a prototype.
C89 (and earlier) allows implicit declaration of functions (use them even if there's no definition or prototype earlier in the compilation unit (this .c + anything you #include
).
So you can compile this in a file by itself, in C89 (or with a warning from most compilers in C99 / C11 mode)
int foo() {
return bar( 123 ); /* implicit declaration of int bar() */
}
But you can't use &bar
as a function pointer
/* int bar(int); necessary if you haven't defined int bar(int x) { ... } */
void *take_fptr() {
return &bar; // error: 'bar' undeclared from GCC
}
You can also construct cases where a declaration is needed to get args passed correctly, e.g. if you want your function to take a float
arg, you need it to be declared, either by a definition or prototype. The "Default Argument Promotions" in the ISO C standard will promote float
to double
when passing an arg to an unprototyped function, or to the ...
part of a variadic function like printf.
(That's why %f
prints a double, not a float, and why %lf
is also a double if it's supported at all. Also why functions like putchar(int)
take their char arg as an int: default promotions of narrow integer types up to int
. Some parts of the C standard library date back to very early C, before the language supported prototypes!)
Or for example, if your function is expecting a long long
, but the caller writes bar( 123 )
, the caller will only infer int
, which may be passed differently from a long long
. But you can fix that by writing bar( 123LL )
, or bar( (long long)123 )
Or if the return type isn't int
(or void
), then you also need the compiler to know about the function via a declaration. Implicitly-declared functions are assumed to return int
. Depending on the calling convention and architecture, you might get away with that for a short
return type, or on some machines even for a char*
, e.g. on 32-bit machines where intptr_t
is int
. (Early C relied on that.)
But in general, e.g. on machines with 64-bit pointers, implicit-int return isn't going to work. Nor will it work for a double
return value, or a struct
.