Your MAKEID
macro is endianness independent. It works identically on both big- and little-endian systems.
The macro may appear to be big-endian specific, but the shifts and bitwise or operations in C++ are all defined in terms of the result they have on the values that are operated on, not the underlying storage of those values.
Doing 42 << 24
is guaranteed to put the value 42
in the most significant 8 bits of the result, regardless of the byte order. Similarly for the bitwise or operation. This means that the result of MAKEID(0x12, 0x34, 0x56, 0x78)
is always 0x12345678
, regardless of the byte ordering of the underlying storage.
If you want to produce an integer whose underlying storage always has the same bit pattern (for example, 0x12, 0x34, 0x56, 0x78), then you really have to rethink your approach. Such an integer will have the value 0x12345678
on a big-endian system, 0x78563412
on a little-endian system and perhaps 0x56781234
on a middle-endian system.
However, if that bit-pattern was received over a communication interface that was defined with a particular byte order (for example big-endian/network byte order), then you must convert any multi-byte values that you receive into the system's native byte order if you want those values to be interpreted correctly by the receiving system and that includes the four byte ID value.
That is why I said in an earlier version of the answer that if you find that on some systems (in particular those where the system's byte order doesn't match the communication's byte order) the ID read from the stream doesn't match the result of MAKEID
, then the likely culprit is the deserialization code. The (de-)serialization code is the most important place to take endianness into account. For example, overlaying the struct you expect over the bytes you received is easy, but is the wrong solution if there can be a byte-order mismatch or a difference in padding.