Search code examples
c++11structcastingvoid-pointersdata-members

Access variables in struct from void pointer


I was wondering if there is a way to access a data member within a struct that is being pointed to by a void*? What I'm trying to explain will hopefully be more apparent in my example code:

int main()
{
  struct S
  {
    int val;
  };
  S s;
  s.val = 5;

  void* p;
  p = malloc(sizeof(S));
  *(struct S*) p = s;
  std::cout<< *(struct S*)p.val << std::endl;

}

I have ran this exact code casting p as *(int*)p and it printed fine, however, using exact code above results in a compilation error. Haven't been able to find an example that quite accomplishes this task. Is it possible to access the data members of the struct after it is casted? why or why not? if so, how?


Solution

  • The . operator has higher precedence than a C-style cast. So *(struct S*)p.val is treated as *((struct S*)(p.val)), which doesn't make sense since p is a pointer and does not have members.

    So you need parentheses to specify what you intended:

    std::cout<< (*(struct S*)p).val << std::endl;
    

    Or equivalently,

    std::cout<< static_cast<S*>(p)->val << std::endl;
    

    [But also: the statement *(struct S*) p = s; technically has undefined behavior, even though all most implementations will allow it. This is because C++ has rules about when an object is created, and there was no object of type S previously at that address, and assignment does not create an object except for some cases involving union members. A similar statement that does not have this problem would be new(p) S{s};.

    Also also: use of malloc or void* is usually not a good idea in C++ in the first place. malloc should only be used when interfacing with a C library that requires it. Anything for which void* seems useful can probably be done more safely using templates. In a few cases a void* might be the only way to do something or "cleverly" avoid code duplication or something, but still use it sparingly and always with extreme caution.]