Odd padding effect when using struct inside a union..??

Hi Folks

I’m experiencing some odd padding behaviour when using a struct inside a union. I am building a packet to be sent via LoRa comms and need to send the various metrics as a series of bytes that can be decoded by the receiving application. I have declared the following struct to hold all the variables (ok, this one is my test one).

// test Tx structure

struct sensorData_t {
byte doorState; // one byte
byte shockState; // one byte
byte upsfailureState; //one byte
uint16_t upsVolts; // two bytes
uint16_t upsFreq; // two bytes
byte anotherbyte; // one byte
};

I then declare the union as below.

union loraPacket_t {
sensorData_t sensor;
byte loraPacket[sizeof(sensorData_t)];
} payload;

I can then populate the union sensor values as follows:

payload.sensor.doorState = 1;
payload.sensor.shockState = 128;
payload.sensor.upsfailureState = 254;
payload.sensor.upsVolts = 2305;
payload.sensor.upsFreq = 501;
payload.sensor.anotherbyte = 64;

Now, by my calculations, the struct should be 8 bytes in size and printing out the values of loraPacket with a for loop, should give me a series of bytes representing the values being stored (If I understand the union correctly).

This does happen, sort of, but at the boundary of a byte type and an uint16_t type I seem to get an additional byte inserted as below. The results of sizeof(sensorData_t) also returns 10 instead of 8. Below, one can see the first three bytes as 01, 80, FE, but there is then a spurious 0 followed by the first of the two byte numbers (LSB first) as 0901 which is 2304 as expected. Then right at the end is another spurious 0. The same happens if I use uint8_t instead of byte.

Starting
Sensor values:
1	128	254	2305 64
Payload size: 10
Payload (DEC): 1	128	254	0	1	9	245	1	64	0	
Payload (HEX): 1	80	FE	0	1	9	F5	1	40	0

Running the same code on the UNO returns results as expected with a sizeof value of 8 and a string of bytes as expected.

What am I missing here?? Is there some sort of padding effect required with the Curie that is not apparent on the UNO etc?

Thanks
Andre

The uint16_t values are being aligned to 2-byte boundaries. The entire struct is made 2-byte aligned, since it has 2-byte contents.

struct sensorData_t {
byte doorState; // one byte
byte shockState; // one byte
byte upsfailureState; //one byte
pad 1 byte to start uint16 on 2-byte boundary.
uint16_t upsVolts; // two bytes
uint16_t upsFreq; // two bytes
byte anotherbyte; // one byte
pad 1 byte to end struct on 2-byte boundary.
}

Examples: http://www.necessaryandsufficient.net/2014/06/struct-padding-in-gcc/
You can make the struct more compact by placing all the larger types first. But the total struct will still be padded to the size of the largest datum.

Hi andref,
you can obtain the exact size by using __attribute__((__packed__)) specifier to your struct
http://grok2.tripod.com/structure_packing.html

You don't see that effect on a UNO because, being an 8 bit MCU, everything is 1byte aligned :slight_smile: