Compiler: I'm personally using gcc, but the question is conceptual. I'm interested in options for any compiler.
Is there a way to tell the C compiler to make struct B
have the same size as struct AB
without sacrificing alignment?
It should also respect alignment when put into an array.
I've tried using __attribute__ ((__packed__, aligned(4)))
but this seems to be the same as not using any attributes (the size is still rounded up to the alignment).
I don't understand how this isn't an obvious improvement: in certain cases it could save quite a bit of space for structs without sacrificing performance (or ergonomics) on field lookups. All it would require for the compiler is to store a (size, alignment) for each struct.
#include <stdio.h>
#include <stdint.h>
struct A { // total size: 6 bytes (actually 8)
uint32_t a0; // 4 bytes
uint16_t a1; // 2 bytes
};
struct B { // total size: 8 bytes (actually 12)
struct A b0; // 6 bytes
uint16_t b1; // 2 bytes
};
struct AB { // total size: 8 bytes (actually 8)
uint32_t a0; // 4 bytes
uint16_t a1; // 2 bytes
uint16_t b1; // 2 bytes
};
// Kind of works, but sacrifices alignment
struct __attribute__ ((__packed__)) Ap {
uint32_t a0; // 4 bytes
uint8_t a1; // 1 byte
};
struct __attribute__ ((__packed__)) Bp {
struct Ap b0;
uint16_t b1;
};
int main() {
printf("sizeof(A) = %u\n", sizeof(struct A)); // 8 (not 6)
printf("sizeof(B) = %u\n", sizeof(struct B)); // 12 (not 8)
printf("sizeof(AB) = %u\n", sizeof(struct AB)); // 8 (same as desired)
printf("sizeof(Ap) = %u\n", sizeof(struct Ap)); // 5 (as desired)
printf("sizeof(Bp) = %u\n", sizeof(struct Bp)); // 7 (not 8)
return 0;
}
The way I've been actually doing this:
#define STRUCT_A \
uint32_t a0; \
uint8_t a1
struct AB {
STRUCT_A; // 6 bytes
uint16_t b1; // 2 bytes
};