Issue
I have an 18 byte struct in C++. I want to read 18 bytes of data from a file straight into this struct. However, my C++ compiler pads the struct to be 20 bytes (4 byte aligned). This is relatively easy to get around for just my compiler alone but I would prefer to use a method that is more reliable cross-platform/cross-compiler.
This is the struct:
struct Test {
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint16_t e;
uint8_t f;
uint16_t g;
uint16_t h;
uint16_t i;
uint16_t j;
uint8_t k;
uint8_t l;
};
Currently I use an ifstream and read it to the struct like so:
Test test;
// file is a binary ifstream
file.read((char*)test.a, 18);
On my system this skips past the two bytes of padding at the beginning of the struct. I could add bytes to the front of the struct to guarantee it to be 32 bytes which would be a valid alignment on most systems, however I don't know if that would actually work with how structs need their elements to be naturally aligned.
Any help on this would be great but I could always end up copying the bytes manually into the attributes 😔.
Solution
You have several options, and as usual, you should choose whatever best fits your needs:
as stated before, don't read/write directly from/to memory, instead write each field separately (kind of how Java people would).
This is the, I think, most portable, but WAY slower than the later methods.reorder the struct to match normal alignment (good practice anyway)
in your example:
struct Test {
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t f; // moved
uint16_t d;
uint16_t e;
// uint8_t f;
uint16_t g;
uint16_t h;
uint16_t i;
uint16_t j;
uint8_t k;
uint8_t l;
uint16_t spare;
};
Note: it still have 2 byte padding, but not in the middle :)
- use
#pragma pack(push, 1)
on the struct to tell the compiler to NOT align the bytes
Note: you may need to place multiple #pragma to support different compilers
#pragma pack(push, 1)
struct Test {
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint16_t e;
uint8_t f;
uint16_t g;
uint16_t h;
uint16_t i;
uint16_t j;
uint8_t k;
uint8_t l;
uint16_t spare;
};
#pragma pack(pop)
I'd like to add that proper alignment helps the CPU process faster, therefore, you don't want to force
pack = 1
on all structs... only those intended to be transmitted or received via communication channel.
Answered By - Tomer W Answer Checked By - Mary Flores (WPSolving Volunteer)