You cannot approach deterministically the layout of a structure or union in C language on different systems.
While many times it could seem that the layout generated by different compilers is the same, you must consider the cases a convergence dictated by practical and functional convenience of compiler design in the ambit of choice freedom left to the programmer by the standard, and thus not effective.
The C11 standard ISO/IEC 9899:2011, almost unchanged from previous standards, clearly stated in paragraph 6.7.2.1 Structure and union specifiers:
Each non-bit-field member of a structure or union object is aligned in an implementation defined manner appropriate to its type.
Even worst the case of bitfields where a large autonomy is left to the programmer:
An implementation may allocate any addressable storage unit large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.
Just count how many times the terms 'implementation-defined' and 'unspecified' appear in the text.
Agreed that to check compiler version, machine and target architecture each run before to use structure or union generated on a different system is unaffordable you should have got a decent answer to your question.
Now let's say that yes, there is a way-around.
Be clear that it is not definitely the solution, but is a common approach that you can found around when data structures exchange is shared between different systems: pack structure elements on value 1 (standard char size).
The use of packing and an accurate structure definition can lead to a sufficiently reliable declaration that can be used on different systems. The packing forces the compiler to remove implementation defined alignments, reducing the eventual incompatibilities due to standard. Moreover avoiding to use bitfields you can remove residual implementation dependent inconsistencies. Last, the access efficiency, due to missing alignment can be recreated by manually adding some dummy declaration inbetween elements, crafted in such a way to force back each field on correct alignment.
As a residual case you have to consider a padding at structure end that some compilers add, but because there is no useful data associated you can ignore it (unless for dynamic space allocation, but again you can deal with it).