Reinterpret_cast void * does not work with function pointers

I want to reinterpret the conversion of a function pointer into a void * variable. The function pointer type will be of type Class* (*)(void*) .

Below is a sample code,

 class Test { int a; }; int main() { Test* *p(void **a); void *f=reinterpret_cast<void*>(p); } 

The above code works well with Visual Studio / x86 compilers. But with the ARM compiler, it gives a compilation error. I do not know why.

Error: # 694: reinterpret_cast cannot throw out hills or other type of classifiers

I read the explanation in Casting a function pointer to another type

I was concerned about the explanation below.

Moving between function pointers and regular pointers (e.g. casting a void (*)(void) to void* ). function pointers are not necessarily the same as regular pointers, since some architectures may contain additional contextual information. This will probably work fine on x86, but remember that this behavior is undefined.

How to make such conversions from void (*)(void*) -> void* efficiently so that at least it compiles almost the same thing in most compilers?

+6
c ++ casting arm
source share
5 answers

reinterpret_cast cannot be used to indicate a pointer to a void* function. Although there are a few additional things that C-cast can do that are not allowed by a combination of static, reinterpretation, and const transforms, this transform is not one of them.

A throw is allowed in C, but its behavior is undefined (i.e., even a round trip is not guaranteed).

Some POSIX functions require proper conversion.

I played with several compilers, which I am here:

  • none of them impede the use of C, even in the highest match mode. Some of them give a warning depending on the level of warning and compliance, others do not warn about what I tried.
  • reinterpret_cast was a mistake with some compilers even at a more relaxed level, while others accepted it in all cases, without even warning.

In the latest draft for C ++ 0X, conditional support for reinterpret_cast between function pointers and object pointers is provided.

Note that if this makes sense or doesn't depend on the goal anymore than the compiler: a portable compiler such as gcc will have the behavior imposed by the target architecture and possibly ABI.

As others note,

 Test* *p(void **a); 

defines a function, not a pointer to a function. But the function for the pointer to the implicit conversion function is done for the reinterpret_cast argument, so the fact that reinterpret_cast get is Test** (*p)(void** a) .

Thanks to Richard, who makes me look at the problem in more detail (for the record, I was mistaken in thinking that the function pointer for the object pointer was one of the cases where C-listing allowed something that was not allowed by C ++ combinations).

+7
source share

reinterpret_cast can only be used for

  • add constant
  • convert pointer to an integral type large enough to hold it back and forth
  • convert function pointer to function pointer of another type
  • convert a pointer to an object to a pointer to an object of another type
  • convert a pointer to a member function to a pointer to a member function of another type
  • convert a pointer to a member object to a pointer to a member object of another type
  • and reinterpret_cast<T&>(x) equivalent to *reinterpret_cast<T*>(&x) (using the built-in & and * ) whenever a second cast is possible using the above rules.

(see section 5.2.10 of the standard)

This means that throwing from a function pointer to void * not possible, but you can apply it to void(*)() .


EDIT (2017): The answer above is only valid for C ++ 03. In C ++ 11 through C ++ 17, this implementation is defined if conversions between function pointers and void * allowed. This usually applies to POSIX compatible systems, since dlsym() declared as a return void * , and it is expected that clients will reinterpret_cast match the correct type of function pointer.

See cppreference.com for a complete list of allowed conversions.

+7
source share

If you just want to store pointers to various types of pointers in a list, then you can use the usual type of function pointer:

 class Test { int a; }; int main() { Test* *p(void **a); void (*f)()=reinterpret_cast<void (*)()>(p); } 

This can be done through reinterpret_cast (5.2.10 / 6):

A pointer to a function can be explicitly converted to a pointer to a function of another type. The effect of calling a function using a pointer to the type of function (8.3.5), which does not match the type used in the definition of the function, is undefined. Except that converting the rvalue of type "pointer to T1" to type "pointer to T2" (where T1 and T2 are types of functions) and back to its original type gives the initial value of the pointer, the result of such a conversion of the pointer is not specified.

+3
source share

Others have indicated that you cannot do this cast (strictly speaking, when you click void* everything that is used with reinterpret_cast is also forbidden, but tacitly carried by compilers. static_cast is for use here).

I usually do the following that does type pun, and this is the recommended way to do it, according to the dlopen man page (which is to do the reverse translation from void* to the function pointer). Taking the address of the function pointer, you get a pointer to the data: a pointer to a function pointer. This will allow you to pass it to void* . It pretends to point to void* (instead of a function pointer), and then reads it.

 Test* (*pF)(void **a); void *p = *(void**)(void*)&pF; 

An intermediate agent added to void* makes it equivalent to be used internally in static_cast internally, and makes GCC silent about the warning of a pun. Using a C ++ Style cast, it looks like a combination of two static_cast 's

 void *p = *static_cast<void**>(static_cast<void*>(&pF)); 

I found that using this method, GCC automatically notices when the left and right types are different in size, and spit out a warning in this case. Needless to say, as with all methods that try to circumvent this limitation, this behavior is undefined.


If you have a function and want void* point to it, you can do it all in one line, but it's a little cumbersome in syntax. Here's how to do it, but I do not recommend it if you have problems reading it - you can use it inside a macro

 // using the function declaration you provided Test** pF(void **a); void *p = *(void**)(void *) &(Test** (* const&)(void **a))&pF; 

The trick is to start being able to make a type, but it must convert the pointer of the temporary function to a lvalue link on const, to which you can take the address, and then continue as described above.

Using explicit C ++ styles static_cast , this looks a lot more complicated because you have to consider it. C style styles automatically touched this. Enjoy!

 int main() { Test** pF(void **a); void *p = *static_cast<void* const*>( static_cast<void const*>( &static_cast<Test** (* const&)(void **a)>(&pF))); } 
+2
source share

should not Test* *p(void **a); to be Test* (*p)(void **a) ?

Perhaps this is your problem?

0
source share

All Articles