My questions:
Here is an example. The questions above boil down to whether C guarantees what main.c
prints: "Function equality: 1"
or "Function equality: 0"
and, in the first case, how does the dynamic loader make that happen.
common.h:
extern void * getc_main;
extern void * getc_shared;
void assign_getc_shared();
main.c:
#include <stdio.h>
#include "common.h"
int main()
{
getc_main = (void*) getc;
assign_getc_shared();
printf("Function equality: %d\n", getc_main == getc_shared);
return 0;
}
shared.c:
#include <stdio.h>
#include "common.h"
void assign_getc_shared()
{
getc_shared = (void*) getc;
}
In Unix this would be compiled with the following commands:
cc -shared -fPIC -o libshared.so shared.c
cc -o main main.c -L. -lshared
And executed with:
LD_LIBRARY_PATH=. ./main
Two function pointers can be compared with the == and != operators, just like any other kind of pointers. We can also compare a function pointer to the NULL pointer using the == and !=
In C, we can use function pointers to avoid code redundancy. For example a simple qsort() function can be used to sort arrays in ascending order or descending or by any other order in case of array of structures. Not only this, with function pointers and void pointers, it is possible to use qsort for any data type.
Function Pointers point to code like normal pointers. In Functions Pointers, function's name can be used to get function's address. A function can also be passed as an arguments and can be returned from a function.
A function pointer, also called a subroutine pointer or procedure pointer, is a pointer that points to a function. As opposed to referencing a data value, a function pointer points to executable code within memory.
C 2011 (N1570 Committee Draft) 6.5.9 6: “Two pointers compare equal if and only if … both are pointers to the same … function …. So, yes, two pointers to the same function compare equal.
When the address of a function is taken in two different object modules, the compiler puts a placeholder in the object code. That placeholder is filled in when the object modules are linked into an executable or linked with a dynamic library at run-time.
For dynamic libraries, either the dynamic loader fills in all placeholders in the executable as necessary or the address of each function is actually the location of some stub code that jumps to the actual function, and a placeholder in or used by that stub code is filled in by the dynamic loader.
Additionally, note that an executable can contain more than one instance of a function. The compiler might insert the function inline in several places or might, for reasons of its own, include a specialization of the function as well as a general version. However, when the address of the function is taken, the compiler must provide the address of a single general version. (Or the compiler must ensure the program behaves as if that were done. E.g., if the compiler can detect that the program does not compare pointers, then it might, in theory, be able to use a different address for some instances of the address of the function.)
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