Function Pointers are Special

Here's something I only learned recently, since it came up when working on Wisp. In C function pointers are incompatible with normal pointers. For example, this is unportable C,

int func (int x);

int main ()
{
  void *p = (void *) &func;
}

This is because function pointers are a different size than other pointers on some architectures, or even within the same architecture with different models (x86's compact and medium models). If the compiler in such a scenario allowed this, the pointer may be truncated and would likely point to the wrong place. It wasn't until I added the -pedantic flag to gcc that it started warning me about situations like the above. The -W -Wall flags are silent here.

The relevant part of the ANSI C standard lists the following as a common, but unportable, extension to the language,

A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function. A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger).

There is a discussion, including an example, on Stack Overflow: Can the Size of Pointers Vary Depending on what's Pointed To?. It also links to this comp.lang.c FAQ question Question 4.13 suggesting the use of a union, which is exactly what I did in Wisp.

I bet this issue only comes up very rarely. How often do you have to store a function pointer in a void pointer? It subverts the type system and is generally a bad idea. I had to do it in Wisp as part of its value polymorphism, which is why it bit me. This is probably why gcc doesn't get very picky over it.

This also means function pointers have less support than normal pointers. For example, printing pointers with printf()'s %p won't work, since it expects a void pointer, so there's no printing them. You can't sort them with qsort(). You can even treat the function pointer as a blob of data to manipulate manually since there's no safe way to make a regular pointer to it. Really, almost any C library function that accepts pointers won't work with function pointers.

So if you want a tricky, unfair, interview question this could be one!

Have a comment on this article? Start a discussion in my public inbox by sending an email to ~skeeto/public-inbox@lists.sr.ht [mailing list etiquette] , or see existing discussions.

null program

Chris Wellons

wellons@nullprogram.com (PGP)
~skeeto/public-inbox@lists.sr.ht (view)