Can you cast a “pointer to a function pointer” to void*

  • A+

Inspired by comments to my answer here.

Is this sequence of steps legal in C standard (C11)?

  1. Make an array of function pointers
  2. Take a pointer to the first entry and cast that pointer to function pointer to void*
  3. Perform pointer arithmetic on that void*
  4. Cast it back to pointer to function pointer and dereference it.

Or equivalently as code:

void foo(void) { ... } void bar(void) { ... }  typedef void (*voidfunc)(void); voidfunc array[] = {foo, bar}; // Step 1  void *ptr1 = array; // Step 2  void *ptr2 = (char*)ptr1 + sizeof(voidfunc); // Step 3  voidfunc bar_ptr = *(voidfunc*)ptr2; // Step 4 

I thought that this would be allowed, as the actual function pointers are only accessed through properly typed pointer. But Andrew Henle pointed out that this doesn't seem to be covered by Standard section Pointers.


Your code is correct.

A pointer to a function is an object and you're casting a pointer to an object (a pointer to a function pointer) to void pointer and back again; and then finally dereferencing a pointer to an object.

As for the char pointer arithmetic, this is referred to by footnote 106 of C11:

106) Another way to approach pointer arithmetic is first to convert the pointer(s) to character pointer(s): In this scheme the integer expression added to or subtracted from the converted pointer is first multiplied by the size of the object originally pointed to, and the resulting pointer is converted back to the original type. For pointer subtraction, the result of the difference between the character pointers is similarly divided by the size of the object originally pointed to. When viewed in this way, an implementation need only provide one extra byte (which may overlap another object in the program) just after the end of the object in order to satisfy the ''one past the last element'' requirements.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: