scugn1zz0
scugn1zz0

Reputation: 337

Why do we need prototype in function?

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

Answers (3)

Peter Cordes
Peter Cordes

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

abhishek_naik
abhishek_naik

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

David Schwartz
David Schwartz

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

Related Questions