0
union Chunk
{
  struct { uint32_t index, total; } m_;
  uint64_t m_PlaceHolder;
} chunk;
chunk.m_.index = 1;
chunk.m_.total = 2;
SendOverTCPNetwork(chunk.m_PlaceHolder); // different platform OS will receive this

A union member is set for 2 integers and then a (combined) long integer is sent over a TCP network as shown above in the pseudo code.

Question: Will the endian-ness of the source machine & destination machine affect the values of the chunk variable?

In other words, will we be receiving the same value on the other side?

timrau
  • 22,578
  • 4
  • 51
  • 64
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Imagine that `SendOverTCPNetwork()` is overloaded for every fundamental type to fix (in case) the endianess of its argument to say network byte order. Assuming local LE and BE over TCP, this would result not only in changing the endianess of `index` and `total` but also their order. – Scheff's Cat Aug 05 '21 at 11:32
  • My adivce is to not have a network API taking integers. You should pass `std::byte`s or `char`s. You should have a conversion function tasked with filling a `byte[]` with data from your integers/structures, using bitshifts as appropriate. This way you are 100% portable and independent on the host endianess. Avoid `hton` and friends. – sbabbi Aug 05 '21 at 11:45
  • Now that the question has been edited, it is type-punning via the union, which is still wrong but in a different way. You're sending data over a network anyway, just cast the object address to `char*` instead of using some intermediate type. – Useless Aug 05 '21 at 23:48

1 Answers1

1

Will the endian-ness of the source machine & destination machine affect the values of the chunk variable?

Yes. Endianness affects all integers, even when they are members of classes. (Except of course signed char and unsigned char).


SendOverTCPNetwork(m_PlaceHolder);

You cannot access non-static members without an object. The example program is ill-formed.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • BTW, I have edited the ill formed pseudo code. Will the values be received as it is if the `m_PlaceHolder` is serialized to a character array with something like Google protobuf? – iammilind Aug 06 '21 at 02:19
  • @iammilind The edited program has undefined behaviour because you read from an inactive member of the union. – eerorika Aug 06 '21 at 02:25
  • My perception was that, once we store `index` & `total` variables in the struct. It also gets stored in `m_PlaceHolder` which is being part of the same `union`. Ultimately this uint64 variable only will get serialized. – iammilind Aug 06 '21 at 05:03
  • @iammilind You cannot do that. You can only read from the union member that is currently active (there are exceptional cases where you can read inactive member, but the example program doesn't have such exception). – eerorika Aug 06 '21 at 05:06
  • 2
    I see, as per [this answer](https://stackoverflow.com/a/52632688/514235) "type punning in unions" is allowed in C, but not in C++, though many compilers like GCC support it. On a side note, does that mean we have to use the bitshifts to achieve the similar result? – iammilind Aug 06 '21 at 05:35
  • @iammilind yeah, bit shifts are the most portable way to serialise data. – eerorika Aug 06 '21 at 05:36
  • BTW, accepted answer to [C++ Accessing inactive union member and undefined behavior?](https://stackoverflow.com/a/11996970/514235), appears to suggest that it's not an undefined behaviour to read an inactive member. The member might be uninitialized formally, but it carries the value properly. So it's safe to use type punning / aliasing in all the platforms. Is that assumption correct? – iammilind Aug 06 '21 at 05:45
  • @iammilind Well, reading an uninitialised value is also UB, so the distinction doesn't seem very important. – eerorika Aug 08 '21 at 08:50