I need to store a function reference as a char*, and later call that function with only the char*.
I am looking for something like:
char* funcRef = (char*)myFunc;
//...
(void (*funcRef)())();
How do you do this? (Note: I am not asking how to call a function by reference, just if its possible to store a reference to it as a char* and then convert it back)
This conversion is not allowed. The allowable conversions are given in section 6.3 Conversions, sub-subsection 6.3.2.3 Pointers, of which paragraphs (6) and (8) apply to function pointers.
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined...
and
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 pointed-to type, the behavior is undefined.
Conversion between pointer to function and pointer to object is not on the allowed list; it is therefore disallowed.
There are systems where pointers to functions and pointers to objects are not interchangeable. The most obvious case is where the size of a function pointer is not the same as the size of an object pointer, such as Harvard architecture, or the 8086 in Compact or Medium model.
The reason your code isn't working is because a char* pointer is not a function pointer. You cannot call a char* as if it was a function. You need to cast that pointer back to a function pointer prior to using it as a function pointer.
Note very well: Whether this will work at all is highly compiler and system dependent.
There is nothing in the C standard that says anything about converting a pointer to a function to a pointer to an object, or vice versa. This is undefined behavior. On the other hand, POSIX standard requires that a compliant implementation must be able to convert a pointer to void to a pointer to a function. (Note: The reverse capability is not required.)
This question is also tagged as C++. Prior to C++11, converting a pointer to a function to a pointer to an object, or vice versa, was illegal. The compiler had to issue a diagnostic message. On POSIX-compliant systems, the compiler would issue a diagnostic and then generate the POSIXly-compliant object code. In C++11 and later, converting converting between pointers to functions to a pointers to an object, or vice versa, is conditionally-supported.
With those caveats, the following works on my POSIX-compliant machine, with multiple compilers. Whether it works on a non-POSIX compliant machine with non-POSIX complaint compilers is anyone's guess.
C++ version:
#include <iostream>
int sqr (int k) { return k*k; }
int p42 (int k) { return k+42; }
void call_callback(void* vptr, int k)
{
using Fptr = int(*)(int);
Fptr fun = reinterpret_cast<Fptr>(vptr);
std::cout << fun(k) << '\n';
}
int main ()
{
call_callback(reinterpret_cast<void*>(sqr), 2);
call_callback(reinterpret_cast<void*>(p42), 2);
}
C version:
#include <stdio.h>
int sqr (int k) { return k*k; }
int p42 (int k) { return k+42; }
void call_callback(void* vptr, int k)
{
printf ("%d\n", ((int(*)(int))(vptr))(k));
}
int main ()
{
call_callback((void*)(sqr), 2);
call_callback((void*)(p42), 2);
}
Related
I have a function that takes a string, an array of strings, and an array of pointers, and looks for the string in the array of strings, and returns the corresponding pointer from the array of pointers. Since I use this for several different things, the pointer array is declared as an array of (void *), and the caller should know what kind of pointers are actually there (and hence what kind of a pointer it gets back as the return value).
When I pass in an array of function pointers, however, I get a warning when I compile with -Wpedantic:
clang:
test.c:40:8: warning: assigning to 'voidfunc' (aka 'void (*)(void)') from 'void *' converts
between void pointer and function pointer [-Wpedantic]
gcc:
test.c:40:8: warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
fptr = find_ptr("quux", name_list, (void **)ptr_list,
Here's a test file, which despite the warning does correctly print "quux":
#include <stdio.h>
#include <string.h>
void foo(void)
{
puts("foo");
}
void bar(void)
{
puts("bar");
}
void quux(void)
{
puts("quux");
}
typedef void (* voidfunc)(void);
voidfunc ptr_list[] = {foo, bar, quux};
char *name_list[] = {"foo", "bar", "quux"};
void *find_ptr(char *name, char *names[], void *ptrs[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = find_ptr("quux", name_list, (void **)ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
Is there any way to fix the warning, other than not compiling with -Wpedantic, or duplicating my find_ptr function, once for function pointers and once for non-function pointers? Is there a better way to achieve what I'm trying to do?
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.
One solution is to add a level of indirection. This helps with lots of things. Instead of storing a pointer to a function, store a pointer to a struct storing a pointer to a function.
typedef struct
{
void (*ptr)(void);
} Func;
Func vf = { voidfunc };
ptrlist[123] = &vf;
etc.
This is something that has long been broken in the C standard and has never been fixed -- there is no generic pointer type that can be used for pointers to functions and pointers to data.
Before the C89 standard, all C compilers allowed converting between pointers of different types, and char * was generally used as a generic pointer that might point to any data type or any function. C89 added void *, but put in a clause that only object pointers could be converted to void *, without ever defining what an object is. The POSIX standard fixes this issue by mandating that void * and function pointers are safely convertable back and forth. So much code exists that converts function pointers to void * and expects it to work properly. As a result, pretty much all C compilers still allow it, and still generate the correct code, as any compiler that did not would be rejected as unusable.
Strictly speaking, if you want to have a generic pointer in C, you need to define a union that can hold either a void * or a void (*)() and use an explicit cast of the function pointer to the correct function pointer type before calling it.
The language lawyering reason is "because C standard does not explicitly allow it." C11 6.3.2.3p1/p8
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.
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.
Notice that a function is not an object in C terminology, hence there is nothing that allows you to convert a pointer to a function to a pointer to void, hence the behaviour is undefined.
Castability to void * is a common extension though. C11 J.5 Common extensions 7:
J.5.7 Function pointer casts
1. 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 (6.5.4).
2. 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) (6.5.4).
This is required by for example POSIX - POSIX has a function dlsym that returns void * but in fact it returns either a pointer to a function or a pointer to an object, depending of the type of the symbol resolved.
As to why this happens - nothing in C standard is undefined or unspecified if the implementations could agree on it. However there were and are platforms where the assumption that a void pointer and function pointer would be of the same width would really make things difficult. One of these is the 8086 16-bit real mode.
And what to use instead then? You can still cast any function pointer to another function pointer, so you can use a generic function pointer void (*)(void) everywhere. If you need both void * and a function pointer, you must use a struct or union or allocate void * to point to the function pointer, or ensure that your code only runs on platforms where J.5.7 is implemented ;)
void (*)() is recommended by some sources too, but right now it seems to trigger a warning in latest GCCs because it doesn't have a prototype.
With some modification you can avoid pointer conversations:
#include <stdio.h>
#include <string.h>
void foo(void)
{
puts("foo");
}
void bar(void)
{
puts("bar");
}
void quux(void)
{
puts("quux");
}
typedef void (* voidfunc)(void);
voidfunc ptr_list[] = {foo, bar, quux};
char *name_list[] = {"foo", "bar", "quux"};
voidfunc find_ptr(char *name, char *names[], voidfunc ptrs[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = find_ptr("quux", name_list, ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
As pointed out in other answers you shouldn't be allowed to assign a function pointer to an object pointer such as a void*. But you can safely assign a function pointer to any function pointer. Use reinterpret_cast in C++.
Let me give an example:
typedef void(*pFun)(void);
double increase(double a){return a+1.0;}
pFun ptrToFunc = reinterpret_cast<void(*)(void)>(increase);
the plain
pFun ptrToFunc = increase;
doesn't compile on several compilers.
I'm answering this old question because it seems that one possible solution is missing from existing answers.
The reason why the compiler forbids the conversion is that sizeof(void(*)(void)) can be different than sizeof(void*). We can make the function more generic, so that it can handle entries of any size:
void *find_item(char *name, char *names[], void *items, int item_size, int item_count)
{
int i;
for (i = 0; i < item_count; i++) {
if (strcmp(name, names[i]) == 0) {
return (char*)items + i * item_size;
}
}
return NULL;
}
int main() {
voidfunc fptr;
fptr = *(voidfunc*)find_item("quux", name_list, ptr_list,
sizeof(ptr_list[0]),
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();
return 0;
}
Now the find_entry() function doesn't need to directly handle the item at all. Instead it just returns a pointer to the array, and the caller can cast it to a pointer-to-funcpointer before dereferencing it.
(The code snippet above assumes the definitions from original question. You can see full code also here: try it online!)
#include <iostream>
void PrintTheValue(int(*func)(int a));
int main(int argc, char **argv) {
PrintTheValue([](int a) {return a; });
return 0;
}
void PrintTheValue(int(*func)(int a)) {
std::cout << *func << std::endl;
}
In my concept of understanding the func, it would be a pointer to an int passed by value. But in this case I'm passing a lambda which doesn't seem to be called anywhere. (So there isn't any value at all?)
When I run this, it doesn't break the program, but instead printed 00EE6F80.
What does this address mean? I have no idea how to interpret it.
In my concept of understanding the func, it would be a pointer to an int passed by value.
func is a pointer to function, which takes an int and returns int.
But in this case I'm passing a lambda which doesn't seem to be called anywhere.
You're passing a lambda without capturing, which could convert to pointer to function implicitly. In PrintTheValue, *func, i.e dereference on the pointer results in a reference to function, and for being passed to operator<< of std::cout, it converts to function pointer again, then converts to bool with value true (as a non-null pointer), then you should get the result 1 (or true with the usage of std::boolalpha). If you want to call on func you could func(42) (or (*func)(42)).
A lambda is an unnamed function object of the closure type.
The crucial part for this case, this class does not overload the operator<<.
When you dereference the passed lambda in *func, there is no overload for operator<<, so it converts to nearest acceptable result which is bool (at first it reverts to a regular pointer).
The documentation:
Dereferencing a function pointer yields the lvalue identifying the pointed-to function
int f();
int (*p)() = f; // pointer p is pointing to f
(*p)(); // function f invoked through the function lvalue
// But no sense in *p
It should print 1 (since non-null pointer), which it does for me (g++). The language does allow us to do so, but there's no sense in dereferencing a pointer to function without calling the function. All the peculiarities of the function pointers are due to that they have one reasonable usage, so anything you do with them will support that usage - #Pete Becker
For more on Function Pointers check here, it will aid.
Will the following work as expected?:
struct A {};
struct B: public A {
int x;
};
void f( B* o ) {
std::cout << o->x << std::endl;
}
int main () {
B b;
b.x = 5;
reinterpret_cast<void(*)(A*)>(f)( &b );
}
Its undefined behaviour to use such pointer after cast:
Any pointer to function can be converted to a pointer to a different function type. Calling the function through a pointer to a different function type is undefined, but converting such pointer back to pointer to the original function type yields the pointer to the original function.
From http://en.cppreference.com/w/cpp/language
So the answer to your question is actually positive - you are allowed to cast but nothing more.
You might ask "what is the point of only casting?" - this is usefull when you want to store various functions in single collection.
See 5.2.10/6 [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined.
That said, note as an example that C++ allows you to dereference a null pointer, so maybe allowed is not the right term.
The following command compiles too:
reinterpret_cast<void(*)(A*, int)>(f)( &b, 42 );
It is allowed, as well as the one in the question, no matter if it works as expected or not (it mostly depends on your expectations, as noted by #luk32 in the comments).
The answer to your question would be yes, the cast is allowed, but the invokation of the function through the new pointer leads to an undefined behavior.
I came across something I don't understand well. Let's suppose I want to pass a character pointer to a function that takes a reference to a void pointer.
void doStuff(void*& buffer)
{
// do something
}
I would usually do something like this :
int main()
{
unsigned char* buffer = 0;
void* b = reinterpret_cast<void *>(buffer);
doStuff(b);
return 0;
}
Why it is not possible to directly pass the reinterpret_cast to the function?
int main()
{
unsigned char* buffer = 0
// This generate a compilation error.
doStuff(reinterpret_cast<void *>(buffer));
// This would be fine.
doStuff(reinterpret_cast<void *&>(buffer));
return 0;
}
There must be a good reason behind this behavior but I don't see it.
In the first example, you're actually passing the pointer variable b. So it works.
In the second example, the first reinterpret_cast returns a pointer (by value), which doesn't match the reference the function should get, while the second returns said reference.
As an example to show you how references work, look at these two functions,
void doSomething( unsigned char *ptr );
void doSomethingRef( unsigned char *&ptr );
Say we have this pointer,
unsigned char *a;
Both functions are called the same way,
doSomething( a ); // Passing pointer a by value
doSomethingRef( a );// Passing pointer a by reference
Though it may look like you're passing it by value, but the function takes a reference so it will be passed as a reference.
A reference is similar to a pointer but it has to be initialized with a left value and can't be null.
Having said that, there are much better alternatives to using void* and especially void*&. void* makes code harder to read and easier to shoot yourself in the foot (if anything by making yourself use these strange casts).
As I said in the comments, you could use a template and not bother with void casting.
template< class T > void doStuff( T *&buffer ) {
...
}
Or,
template< class T > T* doStuff( T* buffer ) {
...
}
EDIT: On a side note, your second example is missing a semicolon,
unsigned char* buffer = 0; // Right here
int main()
{
unsigned char* buffer = 0;
void* b = reinterpret_cast<void *>(buffer);
doStuff(b);
return 0;
}
b is a pointer and doStuff(b) is receiving the address of a pointer. The types match, b is of type void*& (*b is of type void*) and doStuff receives a parameter of type void*&.
int main()
{
unsigned char* buffer = 0
// This generate a compilation error.
doStuff(reinterpret_cast<void *>(buffer));
// This would be fine.
doStuff(reinterpret_cast<void *&>(buffer));
return 0;
}
The second call is like the the call from the above function with b as parameter.
The first call is passing simply a void pointer. The types are different, look closer void* is not the same as void*&
This is how you would specify a reinterpret_cast as the function argument directly, without using an intermediate variable. As others have told you, it's bad practice, but I want to answer your original question. This is for educational purposes only, of course!
#include <iostream>
void doStuff(void*& buffer) {
static const int count = 4;
buffer = static_cast<void*>(static_cast<char*>(buffer) + count);
}
int main() {
char str[] = "0123456789";
char* ptr = str;
std::cout << "Before: '" << ptr << "'\n";
doStuff(*reinterpret_cast<void**>(&ptr)); // <== Here's the Magic!
std::cout << "After: '" << ptr << "'\n";
}
Here we have a pointer to char named ptr and we want to wrangle its type to void*& (a reference to a void pointer), suitable for passing as an argument to function doStuff.
Although references are implemented like pointers, they are semantically more like transparent aliases for another value, so the language doesn't provide the kind of flexibility you get for manipulating pointers.
The trick is: a dereferenced pointer converts directly into a correspondingly typed reference.
So to get a reference to a pointer, we start with a pointer to a pointer:
&ptr (char** - a pointer to a pointer to char)
Now the magic of reinterpret_cast brings us closer to our goal:
reinterpret_cast<void**>(&ptr) (now void** - a pointer to a void pointer)
Finally add the dereferencing operator and our masquerade is complete:
*reinterpret_cast<void**>(&ptr) (void*& - a reference to a void pointer)
This compiles fine in Visual Studio 2013. Here is what the program spits out:
Before: '0123456789'
After: '456789'
The doStuff function successfully advanced ptr by 4 characters, where ptr is a char*, passed by reference as a reinterpret_cast void*.
Obviously, one reason this demonstration works is because doStuff casts the pointer back to a char* to get the updated value. In real-world implementations, all pointers have the same size, so you can probably still get away with this kind of manipulation while switching between types.
But, if you start manipulating pointed-to values using reinterpreted pointers, all kinds of badness can happen. You will also probably be in violation of the "strict aliasing" rule then, so you might as well just change your name to Mister Undefined Behavior and join the circus. Freak.
I'm not sure if this is right, but...
I believe it's as simple matching the argument type:
void doStuff(void* buffer) {
std::cout << reinterpret_cast<char*>(buffer) << std::endl;
return;
}
You could do the above and the int main() would compile correctly.
A reference is different from a copy of a value--the difference is that the copied value doesn't necessarily need to live in a variable or in a place in memory--a copied value could be just a stack variable while a reference shouldn't be able to point to an expiring value. This becomes important once you start playing around with reference and value semantics.
tl;dr: Don't mix references and values when casting. Doing operations on a reference is different than doing operations on a value; even if argument substitution is implicitly casted.
Im learning C++ at the moment, and am having some issues with casting pointers. In the first place I am not sure that what I am trying to do is what I want to do..
I am trying to take a function that can return the appropriate pointer to various method pointers based on string parameters, and to then use the method pointer.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef void* (*plugin_function)(void*);
static class Plugin
{
public:
static bool doBoolStuff(){
return true;// A Simple function that returns true
}
};
void* getFunction(string pluginName, string functionName)
{
if(pluginName =="Bool"){
return &Plugin::doBoolStuff;
//If the string is right it should return a method pointer.
//I think that void* has the ability to point to anything, I am trying
//to use that functionality to create a system where I am able to set
//some parameters and get the appropriate method pointer.
}else{
return NULL;
}
}
int main(int argc, _TCHAR* argv[])
{
void* pluginFunction;
pluginFunction = getFunction("Bool","");
if(pluginFunction == &Plugin::doBoolStuff)cout<<"CastSuccesful!"<<endl;
//This section right here is where my code is breaking.
//
// IntelliSense: expression preceding parentheses of apparent call must have
//(pointer-to-) function type
//c:\Users\Walter\Dropbox\Inscription\MethodCasting\MethodCasting\MethodCasting.cpp
//MethodCasting
cout << "Bool function ->"<< pluginFunction()<<endl;
cout << "--------------------------------"<<endl;
system("pause");
}
Any feedback would be helpful.
Edit: Not true, sorry. As #Stephen Lin pointed out, I failed to read the static modifier... So while what you want doesn't work for non-static member functions, it usually does work for static members using reinterpret_cast (this behavior is implementation-defined):
class Plugin {
public:
static bool foo()
{
std::cout << "Foo called!" << std::endl;
return true;
}
};
void *get_func()
{
return reinterpret_cast<void *>(&Plugin::foo);
}
int main()
{
void *pluginFunction = get_func();
(reinterpret_cast<bool (*)()>(pluginFunction))();
return 0;
}
Original post:
You can't. According to this article:
However, there is no way to cast the void * back to a member function pointer that you could actually use.
I've tried it myself. Actually, all of static_cast, reinterpret_cast and even old C-style casts refused to work - neither with void *, nor with bool (*)() (yes, I've even tried to cast from a non-member function pointer type to a member function type)...
Sorry, C++ doesn't seem to allow us to do this.
It depends on your implementation, if you can do this. In portable C++ you can't. And even if you can, you need explicit casts (in this case reinterpret_cast<>) to convert between different pointer types.
Note that this does not extend to real "method" pointers, that is to non-static member function pointers. You cannot convert between member function pointers and either object pointers or ordinary function pointers. The approach I present at the end can be used, if you only have non-static member function pointers.
Portably reinterpret_cast<> can freely convert between function pointer types and object pointer types - although any use of the result except conversion back to the original type is undefined in almost all cases.
For conversions between object pointer types and function pointer types, the C++11 standard says (§5.2.10 [expr.reinterpret.cast]/8):
Converting a function pointer to an object pointer type or vice versa
is conditionally-supported. The meaning of such a conversion is
implementation-defined, except that if an implementation supports
conversions in both directions, converting a prvalue of one type to
the other type and back, possibly with different cv- qualification,
shall yield the original pointer value.
So, it depends on your implementation (and should be documented in its documentation), if casting a function pointer to a void * compiles and back compiles at all. Alas, if it does, you should get the expected behavior.
In your code the casts are missing. You need a cast to the generic type (in your case void*) in getFunction and you need to cast back to the original type in order to call the function. So you will need to know the original type in main():
void* pluginFunction = getFunction("Bool","");
// ....
cout << "Bool function ->"<< (reinterpret_cast<bool (*)()>(pluginFunction))()<<endl;
A more portable solution would be to use an arbitrary function pointer type, for example void (*)() to pass plugin function pointers around, so that you have:
typedef void (*any_func_ptr)();
// If you wanted to use this for non-static member functions, you could do
// struct AnyClass;
// typedef void (AnyClass::*any_memfun_ptr)();
any_func_ptr getFunction(string pluginName, string functionName)
{
if(pluginName =="Bool"){
return reinterpret_cast<any_func_ptr>(&Plugin::doBoolStuff);
}else{
return NULL;
}
}
int main(int argc, char* argv[])
{
any_func_ptr pluginFunction = getFunction("Bool","");
if(reinterpret_cast<bool (*)()>(pluginFunction) ==
&Plugin::doBoolStuff)
cout<<"CastSuccesful!"<<endl;
cout << "Bool function ->"<< (reinterpret_cast<bool (*)()>(pluginFunction))()<<endl;
}