When the C compiler determines how structures will be represented in memory, it often adds additional bytes in the middle of structures to ensure that fields are aligned on word boundaries. For instance, consider the following striker.
typedef struct myStruct {
short s;
int i;
} MyStruct.
|
You might think that this would take up 6 bytes of memory (2 for the short, 4 for the int.). But in fact, most C compilers, when compiling for 32-bit machines, represent this with 8 bytes -- 2 bytes for the short, 2 padding bytes, and 4 bytes for the int. You can verify this by writing a simple C test program and using the sizeof() operator to determine the size of the structure. The way in which structures are represented is compiler- and machine-dependent. Therefore, in order to both be platform-independent and have the smallest possible file size, you have to write the trace records to the file without any padding.
You might be tempted to simply turn the compiler padding off (for example, using #pragma pack(push, 1)). Unfortunately, this is not an acceptable solution because many processors, including the ARM processors used in PocketPC devices, require values to be byte-aligned in memory in order to function correctly. If you turn the packing off in the structure above, for instance, then the simple statements such as the following statements willcause a Byte Alignment exception.
myStruct mS; mS.i = 1; |
One approach is to leave the structure padding intact and call fwrite to individually write out each element of each structure. While this will work correctly, fwrite can be an expensive call, making this approach inefficient for structures containing many elements.
The approach I'll take is to allocate a small trace buffer. When I want to write a record to the trace file, I'll individually copy each element of the structure to the buffer and then write the buffer to the trace file in a single fwrite call. This uses slightly more memory, but is much more efficient in terms of execution speed.