0

I have 2 identically-sized structs. Their members will never change. The size of their data types is known on the target platform. Is there a reason to not ever do this:

struct foo
{
    unsigned int a; //4 bytes
};

struct bar
{
    unsigned short a; //2 bytes
    unsigned short b; //2 bytes
}

...

foo var1;
bar var2 = *((bar*)((unsigned short*)&foo)); //will this ever cause a runtime error?

I'm not asking if there's a different way to do it (memcpy), or a more readable way, etc...just wondering if this will ever cause an actual error. The code compiles...but I want to make sure I'm not setting myself up for failure later...

Tyson
  • 1,226
  • 1
  • 10
  • 33
  • You have undefined behavior, so technically anything is possible. – NathanOliver Jul 07 '22 at 14:53
  • While it probably won't cause a problem it is UB. Use `std::bitcast` for this sort of thing as it works on objects of the same size like your example. – doug Jul 07 '22 at 14:55
  • Consider what happens if you call a function taking a `foo*` and `bar*` as arguments. The standard says they can not point to the same memory but suddenly they do. So reads and writes through those pointers will get confusing results depending on weather the compiler optimized something to remain in registers or not. Every time you compile your code might behave differently. – Goswin von Brederlow Jul 07 '22 at 14:58
  • 1
    Note that fields can be aligned to 4 bytes, that is why this is UB. Also there is endianes, which can messes with result to. – Marek R Jul 07 '22 at 14:59
  • Thank you, I think I've got my answer now. Will avoid! – Tyson Jul 07 '22 at 14:59
  • It is UB. And why someone should do it? One type is not another type if there is no relation between them. So *why* someone want to do such casts? If you think you *need* to do such things: Start to think about your design instead of what you can do with your compiler to get UB working. Technically nothing will happen as you simply have a pointer to "some" memory. So the monsters will typically sleep but... :-) – Klaus Jul 07 '22 at 15:00
  • `memcpy()` is one way to prevent this - the other is plain bit arithmetic like `a & 0xffff` for the lower 16 bits or `a >> 16` for the higher. Bit arithmetic probably comes with low performance impact as well and provides the added value of being endian agnostic. – Scheff's Cat Jul 07 '22 at 15:03
  • On C++20, there is [std::bit_cast](https://en.cppreference.com/w/cpp/numeric/bit_cast) – prapin Jul 07 '22 at 15:41

0 Answers0