c++ pointer casting help, void* to boolean - c++

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;
}

Related

Address of overloaded function cannot be static_cast to type [duplicate]

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!)

Casting lambda with non-void return type to function pointer

I am trying to cast a lambda function to a function pointer. However, the cast fails when the lambda has a non-void return type. Details see the code snippet.
Is it possible to cast fun2 into a generic function pointer which I can save for later usage?
Update: My intention is to cast all kinds of functions to a "generic function pointer" which can be saved in a std::map. Upon usage, I will cast it back to its original function type.
#include <iostream>
int fun3() { return 1; }
int main(int argc, char *argv[]) {
typedef void (*voidFunctionType)(void);
// Case 1: lambda, return type void
auto fun1 = []() { std::cout << "hello" << std::endl; };
// -> compiles
auto casted_fun1 = (voidFunctionType)fun1;
// Case 2: lambda, return type int
auto fun2 = []() { std::cout << "world" << std::endl; return -1;};
// -> error: invalid cast from type ‘main(int, char**)::<lambda()>’ to type ‘voidFunctionType {aka void (*)()}’
auto casted_fun2 = (voidFunctionType)fun2;
// Case 3: free function, return type int -> compiles
auto casted_fun3 = (voidFunctionType)fun3;
return 0;
}
The problem is that you are using C-style explicit casts. These are notoriously dangerous.
Here in this case the problem is that fun3 (in contrast to fun2) already decays to a function pointer of type int(*)().
You then cast it to void(*)(). This works because the C-style cast will try to do different C++ cast expressions until one works. In particular it will also try a reinterpret_cast.
reinterpret_cast<voidFunctionType>(fun3)
works, because reinterpret_cast can cast any function pointer to any other function pointer.
However, you are not allowed to call the function through the obtained pointer. Doing so causes your program to have undefined behavior. As you can see this cast is of very limited use and dangerous if you are not aware of it.
Don't use C-style casts, use static_cast<voidFunctionType>(fun3) instead and you will get the appropriate compile-time error in both cases.
You cannot use a function (whether free function or lambda) that returns one type as if it returned another (or no) type. Casting the lambda that returns int to void(*)() therefore doesn't make sense.
If you really want to save arbitrary function pointers you can make the lambda cast work by first converting it to a function pointer and then casting it to the destination function pointer type with a reinterpret_cast. I would still not use C style casts, because the reinterpret_cast will at least make it clear what kind of cast you are intending to do:
auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);
The unary + is a common trick to force lambda to function pointer conversion. Note however also that only lambdas without capture can be converted to function pointers.
As I explained above though, you must cast the pointer back to its original type before calling it, so you need to store the type information somewhere. I am not sure how you intend to do that, but you probably need to implement some extended version of std::function, see e.g. this question for how std::function does it.

Is it well defined to use a function pointer that's been cast to another type in a comparison?

Function pointers of dissimilar types can't be directly compared :
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
// Doesn't compile, the comparison is not allowed
std::cout << std::boolalpha << (&foo == &bar) << std::endl;
return 0;
}
However, if one function pointer is cast to the type of the other function pointer, is it defined behavior to compare the result of that cast with the other function pointer?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
auto cast_ptr = reinterpret_cast<decltype(&bar)>(&foo);
// Printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_ptr == &bar) << std::endl;
}
How about if both operators have been cast to a common but different type?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
using cast_type = void(*)();
auto cast_foo = reinterpret_cast<cast_type>(&foo);
auto cast_bar = reinterpret_cast<cast_type>(&bar);
// Also printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_foo == cast_bar) << std::endl;
}
I understand that function pointers compare equal if and only if they both point to nullptr or to the same function. What's not clear to me is rather or not using a function pointer that's been cast to another function pointer type in a comparison is allowed.
Context
I'm maintaining a c++ library with a c compatible API. The library logs every call made to API functions. It's become useful to selectively disable this logging for certain functions at run time. The best current proposal in terms of usability is to supply a new API function which takes as an argument a pointer to the API function whose logging should be suppressed. Since the API functions have different arguments, these pointers would have different types and would need to be cast to a common function pointer type such as void(*)(). Then, before logging an API function call, a container of void(*)() would be searched for the address of the called function to know rather or not to log that call.
From [expr.reinterpret.cast]
A function pointer can be explicitly converted to a function pointer of a different type. [...] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
It is unspecified whether casted function pointers compare equally.
A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined.
Hence it is a natural choice to convert to std::intptr_t or some other suitable type, provided the implementation doesn't use some wacky conversion.
From GCC's documentation
A cast from pointer to integer discards most-significant bits if the pointer representation is larger than the integer type, sign-extends1 if the pointer representation is smaller than the integer type, otherwise the bits are unchanged.
AKA the sane conversion. Which is probably what you'll find in most cases I'd bet.
[1] Future versions of GCC may zero-extend, or use a target-defined ptr_extend pattern. Do not rely on sign extension.

Convert function reference to char* and back

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);
}

Casting a pointer by reference

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.