Can Void* Be Used to Store Function Pointers

can void* be used to store function pointers?

No it may not.

According to the C Standard (6.3.2.3 Pointers)

1 A pointer to void may be converted to or from a pointer to any
object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to
the original pointer.

As for function pointers then

8 A pointer to a function of one type may be converted to a pointer to
a function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to call
a function whose type is not compatible with the referenced type, the
behavior is undefined.

In the C++ Standard there is more detailed definition of pointers (3.9.2 Compound types)

3 The type of a pointer to void or a pointer to an object type is
called an object pointer type....The type of a pointer that can
designate a function is called a function pointer type.

And

4 A pointer to cv-qualified (3.9.3) or cv-unqualified void can be used
to point to objects of unknown type. Such a pointer shall be able to
hold any object pointer. An object of type cv void* shall have the
same representation and alignment requirements as cv char*.

C: How to access a function pointer stored in a void pointer (void *)?

It's a matter of operator precedence: The function call operator have higher precedence than the casting operator.

That means your expression (int (*)(int)) functions[0](x) is really equal to (int (*)(int)) (functions[0](x)).

You need to explicitly add parentheses in the correct places to cast the pointer: ((int (*)(int)) functions[0])(x).


A much better solution IMO would be to have an array of pointers to functions, so the array elements already is of the correct type:

typedef int (*function_ptr)(int);

function_ptr functions[] = { ... };

Then no casting is needed: functions[0](x).

Then you also would be safe from the issues mentioned in the answer by Lundin.

What's the void* of function pointers?

What's the void* of function pointers?

In a way: All pointers to functions.

A special thing about pointer to void is that it can point to any object, and any object pointer can be converted to pointer to void and back, which yields the original pointer.

All pointers to functions can be converted to other pointers to function types and be converted back, yielding the original value.


In another way: There is no analogous pointer type for function pointers in the sense that there is no such pointer type into which all function pointer types would implicitly convert to in same manner as object pointers implicitly convert to void*.


How can I fix this?

Convert the pointer explicitly if you need to, using a cast. Use reinterpret_cast in C++.

P.S. Conversion to void* is not guaranteed to work on all systems and is therefore not universally portable. It is "conditionally supported" according to C++ standard. It is guaranteed to work in POSIX conforming systems.

Storing the pointer to a function pointer in a void*

You are right that all pointer types are object types:

N1570 6.3.5 Types, paragraph 20, fifth list item:

  • A pointer type may be derived from a function type or an object type, called the
    referenced type. A pointer type describes an object whose value provides a reference
    to an entity of the referenced type. A pointer type derived from the referenced type T
    is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a
    referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete
    object type.

But pointers to object types don't necessarily have same size as void* (6.2.5 p28).


  1. A pointer to void shall have the same representation and alignment requirements as a
    pointer to a character type.
    48) Similarly, pointers to qualified or unqualified versions of
    compatible types shall have the same representation and alignment requirements. All
    pointers to structure types shall have the same representation and alignment requirements
    as each other. All pointers to union types shall have the same representation and
    alignment requirements as each other. Pointers to other types need not have the same
    representation or alignment requirements.

However, they can all be converted to void* (6.3.2.3 p1):

  1. A pointer to void may be converted to or from a pointer to any object type. A pointer to
    any object type may be converted to a pointer to void and back again; the result shall
    compare equal to the original pointer.

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

Yes, the code is fine. There's various pitfalls and conversion rules at play here:

  • C splits all types in two main categories: objects and functions. A pointer to a function is a scalar type which in turn is an object. (C17 6.2.5)
  • void* is the generic pointer type for pointers to object type. Any pointer to object type may be converted to/from void*, implicitly. (C17 6.3.2.3 §1).
  • No such generic pointer type exists for pointers to function type. Thus a function pointer cannot be converted to a void* or vice versa. (C17 6.3.2.3 §1)
  • However, any function pointer type can be converted to another function pointer type and back, allowing us to use something like for example void(*)(void) as a generic function pointer type. As long as you don't call the function through the wrong function pointer type, it is fine. (C17 6.3.2.3 §8)

Function pointers point to functions, but they are objects in themselves, just like any pointer is. And so you can use a void* to point at the address of a function pointer.

Therefore, using a void* to point at a function pointer is fine. But not using it to point directly at a function. In case of void *ptr1 = array; the array decays into a pointer to the first element, a void (**)(void) (equivalent to voidfunc* in your example). You may point at such a pointer to function-pointer with a void*.

Furthermore, regarding pointer arithmetic:

  • No pointer arithmetic can be performed on a void*. (C17 6.3.2.2) Such arithmetic is a common non-standard extension that should be avoided. Instead, use a pointer to character type.
  • A pointer to character type may, as a special case, be used to iterate over any object (C17 6.2.3.3 §7). Apart from concerns regarding alignment, doing so is well-defined and does not violate "strict pointer aliasing", should you de-reference the character pointer (C17 6.5 §7).

Therefore, (char*)ptr1 + sizeof(voidfunc); is also fine. You then convert from void* to voidfunc*, to voidfunc which is the original function pointer type stored in the array.

As been noted in comments, you can improve readability of this code significantly by using a typedef to a function type:

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

Why can't I cast a function pointer to (void *)?

You can't fix the warning. In fact, in my opinion it should be a hard error since it's illegal to cast function pointers to other pointers because there are architectures out there today where this isn't just a violation of the C standard but an actual error that will make the code not work. Compilers allow it because many architectures get away with it even though those programs will crash badly on some other architectures. But it's not just a theoretical standard violation, it's something that causes real bugs.

For example on ia64 function pointers are (or at least used to be last time I looked) actually two values, both necessary to make function calls across shared libraries or a program and a shared library. Likewise, the common practice to cast and call function pointers to functions returning a value to a pointer to a function returning void because you know you'll ignore the return value anyway is also illegal on ia64 because that can lead to trap values leaking into registers causing crashes in some unrelated piece of code many instructions later.

Don't cast function pointers. Always have them match types. This is not just standards pedantry, it's an important best practice.

I want to store void pointers to functions along with the type of them

void* can't safely be used as a generic pointer-to-function type (though you might be able to get away with it).

But any function-to-pointer value can be converted to another pointer-to-function type and back again without loss of information. So you can use, for example, void (*)() (pointer to function returning void and taking no arguments) as a generic pointer-to-function type.

As for storing the type, I'm not sure that's possible. If there are only a limited number of possibilities, you can use an enumeration type and a switch statement.

But you'll probably be better off using a design based on inheritance.

Function pointers casting in C++

Converting a void* to a function pointer directly is not allowed (should not compile using any of the casts) in C++98/03. It is conditionally supported in C++0x (an implementation may choose to define the behavior and if it does define it, then it must do what the standard says it should do. A void*, as defined by the C++98/03 standard, was meant to point to objects and not to contain function pointers or member pointers.

Knowing that what you are doing is heavily implementation dependent, here is one option that should compile and work (assuming 32 bit pointers, use long long for 64 bit) on most platforms, even though it is clearly undefined behavior according to the standard:

void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<long>(gptr)) ;

And here is another option that should compile and work, but carries the same caveats with it as the above:

fptr my_ptr = 0;
reinterpret_cast<void*&>(my_ptr) = gptr;

Or, in Slow motion...

// get the address which is an object pointer
void (**object_ptr)() = &my_ptr;

// convert it to void** which is also an object pointer
void ** ppv = reinterpret_cast<void**>(object_ptr);

// assign the address in the memory cell named by 'gptr'
// to the memory cell that is named by 'my_ptr' which is
// the same memory cell that is pointed to
// by the memory cell that is named by 'ppv'
*ppv = gptr;

It essentially exploits the fact that the address of the function pointer is an object pointer (void (**object_ptr)()) - so we can use reinterpret_cast to convert it to any other object pointer: such as void**. We can then follow the address back (by dereferencing the void**) to the actual function pointer and store the value of the gptr there.

yuk - by no means well-defined code - but it should do what you expect it to do on most implementations.

Why is storing a function with different argument type to function pointer with void* argument UB?

A void * can be safely converted to/from any other type, but that's not the conversion you're trying to do. You're trying to convert a int (*)(A *, A *) to a int (*)(void *, void*). Those are two very different things.

The automatic conversion of void * does not apply to the arguments in a function pointer. For two function pointers to be compatible, the number and type of the arguments must be compatible as well as the return type.

One of the reasons for this is that a void * need not have the same representation as other types of pointers. This is fine when simply converting to a void * and back which the standard explicitly allows, however it can be a problem when calling a function.

Suppose a void * is represented with 8 bytes and a struct pointer is represented with 4 bytes. In your example, two 8 byte values would be pushed onto the stack but two 4 bytes values would be read from the stack as parameters in the function. This would result in invalid pointer values which would be subsequently dereferenced.

Function pointer casting parameter to void

c-style casts are fairly lax in their type checking. You should use static_cast instead. This fails to compile:

return static_cast<SEL>(foo);


Related Topics



Leave a reply



Submit