C Structure Padding Initialization | Interrupt

That’s some great data, thanks Noah! Sound conclusions too. I think in C it pays to be explicit.

A potentially useful technique to enable this practice: union with a byte array. In some scenarios (eg. serialisation) I’ve found this useful to have a convenient record based syntax as well as contiguous byte access so you don’t have to rely on implicit assumptions.

For example:

struct foo {
  uint32_t i;
  uint8_t b;
};

union fooWithByteAccess {
  foo fields;
  uint8_t bytes[sizeof(foo)];
}

You can then avoid memcpy and use an initialiser instead:

union fooWithByteAccess f = {.bytes = {0}};

You still need to be very careful - reading and writing to a union using different members is called “type punning”, and if the members are different sizes, or you’re using C90, there are really nasty dragons. See here for some confusing clarifications - as always, trust but verify!

A working example:

#include <stdio.h>
#include <stdint.h>

struct foo {
  uint32_t i;
  uint8_t b;
};

union fooWithByteAccess {
  struct foo fields;
  uint8_t bytes[sizeof(struct foo)];
};

int main(int argc, char *argv[])
{
  union fooWithByteAccess f = {.bytes = {0}};
  f.fields.i = 1234;
  f.fields.b = 123;

  printf("sizeof(f) = %lu\n", sizeof(f));
  printf("f.bytes[0] = 0x%02X\n", f.bytes[0]);
  printf("f.bytes[1] = 0x%02X\n", f.bytes[1]);
  printf("f.bytes[2] = 0x%02X\n", f.bytes[2]);
  printf("f.bytes[3] = 0x%02X\n", f.bytes[3]);
  printf("f.bytes[4] = 0x%02X\n", f.bytes[4]);
  printf("f.bytes[5] = 0x%02X\n", f.bytes[5]);
  printf("f.bytes[6] = 0x%02X\n", f.bytes[6]);
  printf("f.bytes[7] = 0x%02X\n", f.bytes[7]);

  return 0;
}
1 Like