Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit function declarations and linkage

Recently I've learnt about implicit function declarations in C. The main idea is clear but I have some troubles with understanding of the linkage process in this case.

Consider the following code ( file a.c):

#include <stdio.h>

int main() {
    double someValue = f();
    printf("%f\n", someValue);
    return 0;
}

If I try to compile it:

gcc -c a.c -std=c99

I see a warning about implicit declaration of function f().

If I try to compile and link:

gcc a.c -std=c99

I have an undefined reference error. So everything is fine.

Then I add another file (file b.c):

double f(double x) {
    return x;
}

And invoke the next command:

gcc a.c b.c -std=c99

Surprisingly everything is linked successfully. Of course after ./a.out invocation I see a rubbish output.

So, my question is: How are programs with implicitly declared functions linked? And what happens in my example under the hood of compiler/linker?

I read a number of topics on SO like this, this and this one but still have problems.

like image 246
Edgar Rokjān Avatar asked Dec 19 '22 20:12

Edgar Rokjān


1 Answers

First of all, since C99 , implicit declaration of a function is removed from the standard. compilers may support this for compilation of legacy code, but it's nothing mandatory. Quoting the standard foreword,

  • remove implicit function declaration

That said, as per C11, chapter §6.5.2.2

If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined.

So, in your case,

  • the function call itself is implicit declaration (which became non-standard since C99),

  • and due to the mismatch of the function signature [Implicit declaration of a function were assumed to have an int return type], your code invokes undefined behavior.

Just to add a bit more reference, if you try to define the function in the same compilation unit after the call, you'll get a compilation error due to the mismatch signature.

However, your function being defined in a separate compilation unit (and missing prototype declaration), compiler has no way to check the signatures. After the compilation, the linker takes the object files and due to the absence of any type-checking in the linker (and no info in object files either), happily links them. Finally, it will end up in a successful compilation and linking and UB.

like image 128
Sourav Ghosh Avatar answered Jan 05 '23 22:01

Sourav Ghosh