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.
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!)
Hello im confused by typecasting pointers.
I understand that void can hold any type.
So if i have an int * with a value inside of it then i make a void * to the int * can i then typecast it to a char?
It's quite hard to explain what i mean and the title might be wrong but will this work?
And is it safe to do this. I've seen it used quite alot in C. Is this bad practise.
int main() {
int* a = new int{ 65 };
void* v = static_cast<int*>(a);
std::cout << *(static_cast<char *>(v));
}
I understand that void can hold any type.
You understand it wrong. Pointer does not hold data, it points to it. So integer pointer points to memory with holds integer, float pointer points where float is etc. Void pointer just points to some memory, but it says - I do not know what kind of data is there.
Now conversion. Technically you can convert almost any pointer to any (there are exceptions like function pointers or pointers to a member, but they are completely different beasts and it is not what you are asking about) as they all just pointers. But problem happens when you try to access memory where they point to. So if you have int in memory and try to read it as float or vice versa - that's illegal. Now therte is one exception - you can access any data through pointer to char (or unsigned char) as char represents byte. Void pointer is irrelevant here, you can convert from pointer of one type to another without void * involved:
int main() {
int* a = new int{ 65 };
unsigned char *uptr = reinterpret_cast<unsigned char *>( a );
for( size_t i = 0; i < sizeof(int); ++i )
std::cout << static_cast<unsigned int>( uptr[i] ) << ' ';
}
Live example
Note I casted uptr[i] to unsigned int, that is to print bytes as numbers, as C++ stream ( std::cout in this case) will print character as symbol, which would be meaningless in this case.
First any object pointer can be cast to void*. That's the generic "could be anything" solution inherited from C and you should not use it. The C++ way is to use template<typename T> and T* for such cases where you need an anything pointer.
Secondly any object pointer can also be cast to char * as a special case. Casting to char* gives you access to the memory representation of the object. It does not convert the object to a char or anything, you get access to the raw bits for the value stored in the object.
So the reason why casting to void* and then to char* works is that casting any object pointer to char* is valid. The intermediate step to void* is not needed at all.
This only works for char* or unsigned char* or any other variant of char pointer, including std::byte*. You can not static_cast an int* to float* for example and using a void* and intermediate step will not make that work either.
Note: The value printed by the code is implementation defined since the memory representation of an int and a char is defined by the implementation. Specifically their endianness and size of an int and the signedness of char. Apart from that it perfectly valid code.
The question though is: Why do you want to do this?
What is the purpose of a function parameter that has two indirection operators?
Since a call by reference is changing the value of the original variable I thought that a function parameter with two indirection operators might change the address of the original value.
But as my attemp below shows, it does not:
void addrchanger(int**);
int main()
{
int value1 = 4;
int* value1ptr = &value1;
std::cout<<&value1<<std::endl;
addrchanger(&value1ptr);
std::cout<<&value1<<std::endl;
//the address of value1 doesn't change.
}
void addrchanger(int** foo)
{
//this is an attempt to change the address of value1 to the next slot
++**foo;
}
The purpose is to pass a pointer to pointer(s) or a pointer to array(s). Such practise is C-like for historical functions like main() char** argv (that is why you also want an argc, because the size cannot be deduced by the pointer). It is also used when you want to be returned a pointer, so you pass a pointer to a pointer, like in many Win32 functions.
For example in StringFromIID
HRESULT StringFromIID(
REFIID rclsid,
LPOLESTR *lplpsz
);
you would pass a double pointer as the 2nd parameter (a wchar_t**) in order to be returned a pointer, which them must be deallocated like the doc says.
Avoid that completely nowadays in C++ and use std::vector in whatever depth is necessary.
The void addrchanger(int** foo) function can change:
the value: (**foo)++ making int value1 to 5
and address: (*foo)++ making value1ptr point to the next space after value1
I believe you expected the ++**foo to move value1 to the next position, which is not the case.
The pointer to pointer is also useful for matrix declarations, but most libraries such as the GNU scientific library, BLAS, OpenGL glLoadMatrixf(), prefer the use of a single pointer.
When p is of type int **,
++**p
increases the value of the int represented by **p.
In order to change the address of the int pointed to, you would use
++*p
With direct access to your variable, you would use one * less for everything:
int *p;
++*p; // increment the int value
++p; // increment the pointer
But inside such a function, every arguments is just a copy, so if you want to change something outside, you need a pointer to it, which means that one more * is used for everything.
function f(int **p) {
++**p; // increment the int value
++*p; // increment the pointer
// you can also increment the argument
// but you can't know whether it will then
// still point to another int pointer:
++p
}
In addition, you can use & instead of * in C++ which is used only for declaring a variable as a reference and then works like a secret, hidden pointer. You use one less * again, like outside the function at the beginning.
function f(int *&p) {
++*p; // increment the int value
++p; // increment the pointer
// you can also not increment the reference itself,
// as it is a hidden pointer.
}
This sounds dangerous because who would want secret pointers? But it is very common in C++ because people like typing less * all over the place.
Does dereferencing a pointer and passing that to a function which takes its argument by reference create a copy of the object?
In this case the value at the pointer is copied (though this is not necessarily the case as the optimiser may optimise it out).
int val = *pPtr;
In this case however no copy will take place:
int& rVal = *pPtr;
The reason no copy takes place is because a reference is not a machine code level construct. It is a higher level construct and thus is something the compiler uses internally rather than generating specific code for it.
The same, obviously, goes for function parameters.
In the simple case, no. There are more complicated cases, though:
void foo(float const& arg);
int * p = new int(7);
foo(*p);
Here, a temporary object is created, because the type of the dereferenced pointer (int) does not match the base type of the function parameter (float). A conversion sequence exists, and the converted temporary can be bound to arg since that's a const reference.
Hopefully it does not : it would if the called function takes its argument by value.
Furthermore, that's the expected behavior of a reference :
void inc(int &i) { ++i; }
int main()
{
int i = 0;
int *j = &i;
inc(*j);
std::cout << i << std::endl;
}
This code is expected to print 1 because inc takes its argument by reference. Had a copy been made upon inc call, the code would print 0.
No. A reference is more or less just like a pointer with different notation and the restriction that there is no null reference. But like a pointer it contains just the address of an object.
I am trying to write a function that takes a pointer argument, modifies what the pointer points to, and then returns the destination of the pointer as a reference.
I am getting the following error: cannot convert int*** to int* in return
Code:
#include <iostream>
using namespace std;
int* increment(int** i) {
i++;
return &i;
}
int main() {
int a=24;
int *p=&a;
int *p2;
p2=increment(&p);
cout<<p2;
}
Thanks for helping!
If you indeed mean "return the destination of the pointer as a reference", then I think the return type you're after is int& rather than int*.
This can be one of the confusing things about C++, since & and * have different meanings depending on where you use them. & is "Reference type" if you're talking about a variable definition or return type; but it means "Address of" if it's in front of a variable being used after it's defined.
I could be completely mistaken, but it seems to me that you've gotten these two meanings mixed up; and since you want to return a reference, you've written "return &i", since & is used for references. However, in this case, it returns the address of i. And since i is a pointer to a pointer to an int, in this line of code:
int* increment(int** i) { i++; return &i;}
you are returning the address of a pointer to a pointer to an int. That is why you are getting your error message cannot convert int***' to int*.
Let's walk through your code line by line. You are after a program that takes a pointer and returns a reference. So that would be:
int& increment(int* i)
We don't need the double pointer that you had in your code (unless you want a pointer to a pointer). Then you want it to modify what the pointer points to:
(*i)++;
And then return the destination of the pointer as a reference:
return *i;
Here, we are dereferencing i. Remember that using references lets you treat them like normal variables, and handles the pointer stuff for you. So C++ will figure out that you want it to be a reference.
Then, to use your code, you can do pretty much what you had, but using less pointers:
int a=24;
int *p=&a;
int *p2;
p2 = increment(p);
I haven't tested any of this, so anyone may feel free to edit my answer and fix it if I've got something wrong.
int* increment(int** i) { (**i)++; return *i;}
and
cout << *p2;