However you do it, unit test the hell out of it. Compilers and platforms vary a lot on these points, so don't ever assume blindly that it is consistent.
Compilers may change struct alignment at their whim (for performance reasons, for example). Asking for some restrictions are generally compiler specific, though this one is supported by MSVC and gcc (through an extension)
#pragma pack(push, 1) struct Foo { // .. }; #pragma pack(pop)
This forces it to align on 1 byte boundaries, so no booleans.
If you want to be fully compliant, then serialize each field yourself. It really isn't all that much work.
You will also have to deal with endianness, as mentioned by others.