Afternoon everyone - I have a question about function pointers. I want
to convert a function pointer to a string (which I will use elsewhere
in the code) and I then want to reconvert this string back to a
function pointer and call it.
I am thinking I can probably do something like
char * thestring=malloc(sizeof(char) * 30));
sprintf(thestring,"%p\0",function pointer);
But how would I convert this string back into a function pointer -
especially in a way which is portable?
Unfortunately, the easy way to do this is not portable, because
pointers to functions are inherently incompatible with other pointers,
in standard C (and I've used at least one implementation where function
pointers were quite a bit larger than pointers to data).
If you want to limit yourself to implementations where function pointers
are represented in the same way as other pointers, you can use the %P
format specifier of scanf, which the C99 standard says,
"Matches an implementation-defined set of sequences, which should be the
same as the set of sequences that may be produced by the %p conversion of
the fprintf function."
But both %p and %P operate on pointers to void, so you would have to be
sure
that your implementation can do the conversion to and from (void *) without
loss of information. If doing it this way, the code would be something
like:
char *thestring = malloc(30);/* but there's no way of knowing
* whether 30 is large enough, except
* by trial and error on each platform.
* sizeof(char) is 1, by definition, so
* is redundant noise
*/
sprintf(thestring, "%p", (void *)functionptr);
/* putting \0 in format makes the string end with TWO null chars */
then later
void * void_star_fp;
int (*fp)(); /* or whatever you want your function pointer to look like
*/
sscanf(thestring, "%P", &void_star_fp);
fp = (int (*)())void_star_fp;
-----------
The above is an interesting exercise, showing how to encode a data pointer
into a string and reconstruct it, including the important point that the
argument corresponding to %P in a scanf format MUST BE a (void **), and
NOT a pointer to some other pointer type.
But the actual portable way to encode a function pointer into a string and
then reconstruct it would be to treat the pointer as an array of unsigned
char, and encode and decode it byte by byte, e.g.
typedef int (*Fptr)(); /* to avoid having to repeatedly type (int (*)()) */
/* [replace the int and the () with whatever matches your functions'
return value and parameters.
*/
#define HEX_DIGITS_PER_CHAR (CHAR_BIT + 3)/4)
#define STRING_SIZE (sizeof(Fptr) * HEX_DIGITS_PER_CHAR + 1)
char thestring[STRING_SIZE]; /* unless you really need malloc */
size_t i;
unsigned char *fptr = (unsigned char *)&my_function_pointer;
for (i = 0; i < sizeof (Fptr); ++i) {
sprintf(thestring + (i * HEX_DIGITS_PER_CHAR), "%0*hhx",
HEX_DIGITS_PER_CHAR, fptr + i);
}
and then reconstruct the pointer later by treating the target pointer
as an array of unsigned chars, and using sscanf to read the hex values
and place them in those unsigned chars.
Disclaimer: THe above code is totally untested, and probably contains
bugs.
I haven't put a lot of thought into it (e.g. I almost posted this with
"%hhx"
as the sprintf format specifier).