Ok so I have this code:
str.c:
char *str = "example";
main.c:
int str(void);
int main(void)
{
str();
return 0;
}
makefile:
CC = gcc
CFLAGS = -Wall -g
all: main
main: main.o str.o
main.o: main.c
str.o: str.c
clean:
rm -rf *.o main
On the first sight, one might say that it's an undefined reference error or something like that. But the compiler simply accepts this code.
The question is, why don't I get a compile error?
It's clear that the function is not properly defined. If I use gdb to break on the str() call, I get a warning type Function str not defined..
First of all (as other have pointed out already) if one could have expected an error while "building" the executable main
, then during the linking phase, namely because int str(void)
is not defined in any translation unit (.c file) so the compiler did not place it in any object file (.o).
But unfortunately you have char * str = "..."
defined.
C (as opposed to other languages, for example C++) does not annotate functions, it does not create a function-signature, but just only the function's name, a symbol name. It does so as well for all other objects.
So the linker has no other choice but checking the names of the symbols available, and if they match 1:1 to link them. It cannot double check, because the compiler did not put any verification information into the object files.
If you had an implementation (a definition, as opposed to just a declaration) of int str(void)
somewhere inside the objects to link, then the linker would have noticed that there is no 1:1 match so something fishy might be going on.
The compiler is happy if you give a function prototype int str(void);
, however, the linker will try to resolve the reference and you will get an unresolved reference from it.
That's where the error will come from.
The prototype is your promise to the compiler that the function is defined somewhere. The linker makes sure you kept that promise.
Code is compiled without problems.
int str(void); //Compiler needs this to know how to prepare future calls to this function
int main(void) {
str(); //Here compiler knows about str function and how it looks like
return 0;
}
When str()
is called in main.c, compiler will prepare for call and since before main you have function prototype, compiler knows how to call it and will go further, he is fint with it.
Linker is the one who at the end tries to put all functions together and then you will get error like Function not found because str()
function was never actually compiled.
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