In C, how come a function may have several declarations but only one definition? Can someone elaborate on that please!
In order to allow multiple definitions, we must require the definition be functionally identical - otherwise you must have some way to decide which to run, at which point you might as well give them different names.
Proving that two function definitions are identical is a non-trivial problem. Since functions may be declared in multiple translation units, you would need to compare them at the link stage in order to prove they were identical. This is a problem when you start dealing with compiler optimizations which may take into account the other contents of these translation units. For example, consider:
const char *foo() {
return "world";
}
Simple enough, right? Now we compile two files. a.c contains only foo. b.c contains this as well:
const char *bar() {
return "Hello world";
}
The compiler may choose to make foo()'s "world" point into the middle of bar()'s "Hello world". The linker must somehow determine that the two foo()s are identical, even though they point into non-identical constant data.
A bigger issue comes in when aliasing rules are considered. Consider:
void frob(int *p);
int foo() {
int x = 1;
x++;
frob(&x);
}
Compiled alone, this might result in assembly code similar to:
foo:
sub %esp, 4 ; allocate stack space for x
mov dword [%esp], 2 ; set x to 2 (x++ combined with initialization)
push %esp ; push %x to the stack as frob's argument
call frob
mov %eax, dword [%esp+4] ; load the value of x into eax for the return value
add %esp, 8 ; clear the stack of frob's argument and x
ret ; return
Now let's compile it with a definition of frob in scope:
void frob(int *p) { /* no-op */ }
Now we have:
frob:
ret ; return
foo:
mov %eax, 2 ; return value = 2
ret ; return
How can the linker tell the two foo definitions are identical?
Given the difficulties of proving function bodies identical, C opts to simply forbid you from defining the same function twice. C++ uses a different approach for inline and template functions; it simply doesn't check, and assumes they're identical.
As for declarations on the other hand, there are defined rules for proving compatibility, so there's no problem in allowing multiple compatible declarations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With