Suppose we have the following iterface to a library:
// my_interface.h
typedef float (*myfunc)(float);
myfunc get_the_func();
And suppose that the implementation is as follows:
// my_impl.c
#include <math.h>
myfunc get_the_func() {
return sinf;
}
And now suppose the client code does the following:
#include "my_interface.h"
...
myfunc func = get_the_func();
printf("%f\n", func(0.0f));
Does the standard guarantee that get_the_function() will return the address of the standard math library sinf()? If so, where in the standard is this implied? Please note the sinf() is not explicitly called anywhere.
The standard does not require external functions to be called: being referenced is enough to be kept in the results of translation. According to the standard's section 5.1.1.2.1, during the eights (and last) phase of translation
All external object and function references are resolved. Library components are linked to satisfy external references to functions and objects not defined in the current translation.
Since returning a pointer to a function is considered a reference to it, the standard guarantees that sinf
will be linked to whatever implementation that you supply to the linker, which may or may not be the one coming from the standard math library.
The C standard doesn't guarantee that get_the_function()
will return the address of the sinf
function in the math library. The C standard guarantees that whatever the pointer is returned will be callable as if you called the sinf
function and it will compare equal to any other pointer to that function.
On some architectures you might get a pointer to a descriptor of the function which the compiler handles specially and I've also seen function pointer values pointing to a dynamic linking trampoline and not the function itself.
I recall a discussion on the gcc mailing lists around 10 years ago if a function pointer cast to (void *) actually needs to compare equal to another function pointer cast to (void *) which was in connection with how IA64 implements function pointers (they could point to different descriptor structs in different libraries, which meant that to correctly implement compares the compiler would have to compare the contents of the descriptors and not the pointers themselves). But I don't remember what the standards lawyers decided and/or if this was solved in the linker.
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