Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, how come function may have several declarations but only one definition?

Tags:

c

In C, how come a function may have several declarations but only one definition? Can someone elaborate on that please!

like image 779
navanshu Avatar asked Oct 23 '25 23:10

navanshu


1 Answers

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.

like image 72
bdonlan Avatar answered Oct 25 '25 12:10

bdonlan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!