Turns out both micros are both little endian but one is 8 bit the other is 32. The problem is the padding. Im still after a solution that is portable in case I move to another micro thats big endian. Is big endian not so common I shouldnt worry about it?
While DavidAlfa's endianness attribute would be a little bit "weird" beast, at least
packed attribute/pragma is available on
any compiler worth using, so even if still not standard C, it's pretty damn common. And despite some claims on this very forum, I have never seen or heard any compiler generating unaligned accesses using a packed struct, but of course being non-standard, it's not
guaranteed portable, even if it practically is.
However, if you can freely design the structure, I strongly suggest to make the members naturally-aligned for the 32-bit target (it will obviously be aligned for the 8-bitter, too). Natural alignment generates smallest and fastest code. (Unaligned members need more instructions, which compiler automagically generates for packed structs, or which you manually write using the nctnico's way, with bitshifts etc.)
Natural alignment means that 32-bit members start at 4-byte boundaries, 16-bit members at 2-byte boundaries etc.. You get closest to this (minimum padding required) by simply ordering the members from biggest to smallest (ages old trick). Then, if padding is still needed for natural alignment, you can pad members manually - this has added benefit of it becoming documented, and giving you explicit
reserved members you can later start using when extending the protocol. It's also more obvious to zero such explicit padding members (uninitialized compiler-generated padding is a semi-common safety bug). Add a comment to reserved members such as "always write to 0". Then any non-zero value would denote you are using the extended feature.
When you manually pad the struct to natural alignment, compiler has no reason to add more padding, and thus a packed attribute becomes nearly irrelevant (however, see the important point below). It's a good idea to add a few static_asserts() to verify the offsetof() of a few members, and maybe sizeof of your struct. Then any false assumption on your behalf would simply result in an error.
Remember, if you pointer-cast your struct type over a randomly aligned byte buffer, it will only work if the struct type has the packed attribute. If you ever plan doing that, the options are packed structs and restricting yourself to compilers which behave this way (so practically anything sane), or creating a temporary struct object and memcpying to it, or using accessor helper functions which internally use bitshifts, anding and orring.