Reputation: 337
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)?
Upvotes: 7
Views: 6140
Reputation: 365342
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
.
Upvotes: 2
Reputation: 1297
Consider the program below:
#include <stdio.h>
void add(int, int);
int main() {
add(5, 3);
return 0;
}
void add(int a, int b) {
printf("%d", a+b);
}
Here, when you call add(5, 3)
from main()
, the compiler knows what add()
is - the parameters it takes and the return type, thanks to the statement void add(int, int)
in line 3. If this statement is commented out, then the compiler won't know what add()
is and would give you an error. Thus, line 3 tells the compiler that you have defined the function add()
later, which makes it perfectly eligible to be used in main()
. Alternately, if you write the add()
function before main()
, then the compiler knows what add()
is when you call it; so a function prototype is not required in this case.
Hope this is useful.
Upvotes: 8
Reputation: 182827
The definition of the function may not be known at that time. Imagine a program that calls malloc
to allocate memory. At compile time, nobody has any idea what allocator the program will be using at run time. So how can you define the function then?
Upvotes: -1