1

I have union

union Data
{
   uint8_t * utf8;
   uint16_t * utf16;
   uint32_t * utf32;
};

and a variable Data data; How can I cast data to void*? The union size is equal to size of any pointer because It contains only pointers. So why I can't do this like (void*)data

patrykbajos
  • 384
  • 3
  • 17
  • Same reason that with `struct X {} x;` you cannot cast `x` to `void*` even though its size is no larger than that of `void*`. – Kerrek SB May 26 '16 at 12:06
  • If you to be really( again really) able to cast object of type `Data` to `void*` you can overload *typecast operator* – PcAF May 26 '16 at 12:09
  • 2
    The correct way is to take the active member and then convert that to a `void*`. – MicroVirus May 26 '16 at 12:23
  • 1
    Also, the C++ standard doesn't guarantee you that all sizes are the same, though in practice they are; see [Is the sizeof(some pointer) always equal to four?](http://stackoverflow.com/questions/399003/is-the-sizeofsome-pointer-always-equal-to-four) – MicroVirus May 26 '16 at 12:29
  • 1
    Why do you need a union? Why not just keep it all as `void*`? – n. m. could be an AI May 26 '16 at 12:33
  • @MicroVirus, but when `sizeof(char*)` is 4 then `sizeof(void*)` will be 4, when `sizeof(char*)` is 8 `sizeof(void*)` will be 8? – patrykbajos May 26 '16 at 12:34
  • @bajos In practice, yes, that is how it works, but it isn't guaranteed by the C++ standard. – MicroVirus May 26 '16 at 12:35
  • @bajos it is guaranteed that `sizeof(char*)==sizeof(void*)`, but this is not guaranteed about any other type. – n. m. could be an AI May 26 '16 at 12:41
  • So if you set uint16_t x = 1; data.utf16 = &x; then you can't get a void* pointing to x unless you know that utf16 was the last element that was set. – gnasher729 May 26 '16 at 12:47

3 Answers3

1

you can not cast object to void* but you can cast it's pointer to void * like this:

Data d;
void * d_ptr = (void *) &d;

and get object again like these:

Data &d2 = * (Data *) d_ptr;
Data *d3 = (Data *)d_ptr;
Hossein Nasr
  • 1,436
  • 2
  • 20
  • 40
0

I've found solution:

    union Data
   {
      uint8_t * utf8;
      uint16_t * utf16;
      uint32_t * utf32;
      void* raw;
   };

When I return data.raw It should give result same (but without compilation error) as (void*) data (?).

patrykbajos
  • 384
  • 3
  • 17
  • This may work in practice, but it is not C++ standards compliant. See [Unions and type-punning](http://stackoverflow.com/questions/25664848/unions-and-type-punning). It may fail when compilers use aggressive optimisations based on strict aliasing. – MicroVirus May 26 '16 at 12:33
  • You could also make raw a `uintptr_t'. – Chris Becke May 26 '16 at 12:35
  • @MicroVirus Would the "volatile" keyword help prevent this behavior from the compiler? – DeathByTensors May 26 '16 at 12:40
  • @DrewBuckley It may or may not, depending on where you place the `volatile`. It isn't a total solution. – MicroVirus May 26 '16 at 12:42
  • @MicroVirus `union { Data data; void* ptr; }` then? – Chris Becke May 26 '16 at 12:44
  • @ChrisBecke Also technically not legal in C++ (though legal in C99 onwards). In practice, this answer works, but when looking at a standards point of view it's not legal code. – MicroVirus May 26 '16 at 12:48
-1

You can use explicit cast using static_cast

Data d; 
int8_t s;
s = 0x11;
d.utf8 = &s;

void* p = static_cast<void*>(d.utf8);
uint8_t* utf8 = static_cast<uint8_t*>(p);
Damian
  • 4,395
  • 4
  • 39
  • 67
  • This is only half the story. If `utf16` was the active member, by setting `d.utf16 = ...`, then you'd need to also access that member, technically speaking, in `void *p = static_cast(d.utf16)`. – MicroVirus May 26 '16 at 12:36
  • Unions will use the memory of the largest data member which in this case is a pointer. So I don't really get your point. – Damian May 26 '16 at 12:39
  • uint8_t* can be 8 bytes, while uint16_t* is 4 bytes. What would you expect if Data d contains 4 byte pointer and 4 byte rubbish and run your code? – gnasher729 May 26 '16 at 12:49
  • As I said a union occupies only as much space as its largest member. – Damian May 26 '16 at 13:02