1

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?

demogorgon
  • 474
  • 4
  • 20

1 Answers1

1

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.]

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • Thanks for your response! It was extremely insightful and straightforward. I am skeptical about using `void*` as well. My situation is that I have child classes that essentially get a structure from a base class. Problem is that I don't know which type of `struct` will be provided until run time. So `void*` was my way of trying to "capture" the `struct` no matter the type. Any thoughts or ideas? – demogorgon Jun 26 '18 at 23:54
  • Possibly an interface plus template implementation sort of thing, or maybe a `std::variant` (or `boost::variant` if C++17 is not available). But it's hard to say without more details. Maybe you could open another question about that. – aschepler Jun 27 '18 at 02:17
  • Cool, thanks! Performance is a huge consideration and pretty critical. I have looked into `boost::variant` but have been unable to find timing complexities. I will try to dive deeper into it. – demogorgon Jun 27 '18 at 02:32