Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert pointer to data member to void *

I know that I can get a pointer to data member for a class or struct but the last line of the following code fails to compile:

struct abc
{
    int a;
    int b;
    char c;
};

int main()
{
    char abc::*ptt1 = &abc::c;
    void *another_ptr = (void*)ptt1;
}

Why can't I convert ptt1 to another_ptr? We're talking about pointers so one pointer should have a similar dimension to another one (although conceptually different)?

like image 751
Paul Avatar asked Mar 21 '13 12:03

Paul


People also ask

What is void * pointer?

The void pointer in C is a pointer that is not associated with any data types. It points to some data location in the storage. This means that it points to the address of variables. It is also called the general purpose pointer. In C, malloc() and calloc() functions return void * or generic pointers.

What is const void * in C?

const void is a type which you can form a pointer to. It's similar to a normal void pointer, but conversions work differently. For example, a const int* cannot be implicitly converted to a void* , but it can be implicitly converted to a const void* .

Is typecast from void * into int * Possible?

You're return ing the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.


2 Answers

A pointer to non-static class member type is not the same as a object pointer type; they behave very differently. In fact, you cannot even dereference a pointer to member with *. To access a member through a pointer to member, you use the .* and ->* operators instead. If you could cast it to an object pointer type like this, what would happen, then, if you dereferenced it with *?

Only object pointer types have a standard conversion to void* (§4.10):

A prvalue of type "pointer to cv T," where T is an object type, can be converted to a prvalue of type "pointer to cv void".

They're so different that the standard even goes out of its way to make sure that the term "pointer" doesn't include pointers to non-static members (§3.9.2):

Except for pointers to static members, text referring to "pointers" does not apply to pointers to members.

like image 124
Joseph Mansfield Avatar answered Sep 21 '22 22:09

Joseph Mansfield


The main reason is because there is no requirement that a pointer to member have the same size and representation as a pointer to data. In practice, it's hard to imagine a pointer to a data member not being able to fit into a void*, since a pointer to a data member really only needs to contain an offset. Roughly speaking, a pointer to a data member will never need to be larger than a size_t, and a void* must be at least as large as a size_t. On the other hand, it could easily contain bit patterns which weren't legal in a pointer. In fact, as Steve Jessop points out, pointers to member do require additional information, since if the member is in a virtual base, its offset depends on the most derived class, and must be calculated dynamically, based on additional information in the pointer.

More generally, a void* can only contain a pointer to data. It must be as large as the largest data pointer (typically a char*), but pointers to functions, and member pointers, can be larger, and not fit (and pointer to member functions almost never fit).

like image 41
James Kanze Avatar answered Sep 20 '22 22:09

James Kanze