Very few chipsets allow placing values at the wrong alignment.
x86 is one of the few that allowed integers to be placed at any alignment, accessing a 4-byte integer at any offset is allowed but suffers a performance penalty that is not directly visible to you. On most other chipsets that crashes.
Note that other data types, misaligned data can also cause crashes on x86, such as trying to load into XMM, YMM, or other SIMD registers.
float value = doLittleBigEndianConversion(doUnalignedReading(reinterpret_cast<int*>(ucharPtr + offset));
Icky. I disagree, because you are still operating at the wrong type of int*.
When packing and unpacking data by creating an object of the correct type, such as an int32, or float, or double, or whatever, then doing operations that do not rely on alignment such as memcpy or single byte accesses.
Often that means a packer and unpacker class that process your stream. Inside it you have a function similar to this:
float unpackFloat(unsigned char* offset) {
// Other code and static assertions ensure float is four bytes and otherwise that our processor is supported
float result;
*((unsigned char*)(&result)) = *offset;
*((unsigned char*)(&result)+1) = *offset+1;
*((unsigned char*)(&result)+2) = *offset+2;
*((unsigned char*)(&result)+3) = *offset+3;
return result;
}
Repeat with packing functions and unpacking functions for all types you care about.
There are many serialization libraries that are already written and debugged that do this for you. No need to reinvent the wheel.