struct SOME_STRUCT { unsigned short objectId; unsigned long length; };
We read sizeof(SOME_STRUCT) from buffer. sizeof(SOME_STRUCT) - Not sure why the lenght is Eight bytes when the structure contains a short and a long.
The data in the buffer is as follows:
01 00 00 08 00 00 00 00 00 00
We thought we were reading six bytes from the buffer but we're reading eight bytes from it. objectId is 0x0001 length is 0x00000000
We're using Keil compiler Armcc.Exe V4.1.0.894
It looks like we have some kind of alignment issue? Does this compiler only read from word aligned addresses ? What is the root cause of the problem ? Do we need some kind of PACK or packed keyword so compiler reads six bytes from the buffer instead of eight ?
Reading from the struct shows wrong values because you have mapped the struct on top of data that have a totally different memory map.
char buf[100]; mystruct_t mystruct; void *p; read_raw_data(buf,6); p = buf; p = unpack_u16(p,&mystruct.u16field); p = unpack_u32(p,&mystruct.u32field);
Remember that the C language standard doesn't promise that you can perform any random memory copy to a struct and get the expected result.
When assigning, you either assign to individual fields, or you assign the full struct from another variable of a compatible struct.
Your issue comes from you having made an assumption without being backed by the language standard.
You did an incorrect assign - and ended up with invalid content. That is what to consider when "cheating" on the language standard. You broke your side of the contract and the compiler ended up producing code with undefined results.
Note that using a packed struct only solves align issues by forcing the removal of pad bytes and forcing the compiler to producing very large and inefficient code. But a packed struct still doesn't solve the other issue possible - that the source of the data might use a different byte order than the target processor.
Having explicitly written pack/unpack code means the code can function without issues from byte order or align requirements. Also remember that the individual data types in C can mean different things depending on architecture and compiler. What is 16 bits on one processor might be 32 bits on another processor. So the header files has special provisioning for data types of exact sizes. Explicit pack code would obviously know if it packs/unpacks a 16-bit or a 32-bit value.
Thank you for great replies. Learned something very useful.
unpack routines that I write might not be portable because in a different platform the soure of data might have different byte order.
The unpack code could be 100% portable by picking up the individual bytes in exactly the order you - or the sending side - has defined them to be in.
Remember that the unpack code can't just play with void pointer and type-cast it into a short or a long. That would result in an exception if the data isn't properly aligned.
So your code would work on a byte array and pick up byte after byte and properly shift to the correct position and merge into a short or a long number. But remember that right-shift of signed numbers behaves different from unsigned numbers depending on sign bit.