Un altro utilizzo dell'array di lunghezza zero è come etichetta con nome all'interno di una struttura per assistere il controllo dell'offset della struttura in fase di compilazione.
Supponiamo di avere alcune definizioni di strutture di grandi dimensioni (che si estendono su più linee di cache) per assicurarti che siano allineate al limite della linea di cache sia all'inizio che al centro, dove attraversa il confine.
struct example_large_s
{
u32 first; // align to CL
u32 data;
....
u64 *second; // align to second CL after the first one
....
};
Nel codice puoi dichiararli usando estensioni GCC come:
__attribute__((aligned(CACHE_LINE_BYTES)))
Ma vuoi comunque assicurarti che venga applicato in runtime.
ASSERT (offsetof (example_large_s, first) == 0);
ASSERT (offsetof (example_large_s, second) == CACHE_LINE_BYTES);
Ciò funzionerebbe per una singola struttura, ma sarebbe difficile coprire molte strutture, ciascuna con un nome membro diverso da allineare. Molto probabilmente otterrai codice come di seguito in cui devi trovare i nomi del primo membro di ogni struttura:
assert (offsetof (one_struct, <name_of_first_member>) == 0);
assert (offsetof (one_struct, <name_of_second_member>) == CACHE_LINE_BYTES);
assert (offsetof (another_struct, <name_of_first_member>) == 0);
assert (offsetof (another_struct, <name_of_second_member>) == CACHE_LINE_BYTES);
Invece di andare in questo modo, puoi dichiarare un array di lunghezza zero nella struttura che funge da etichetta con un nome coerente ma non occupa spazio.
#define CACHE_LINE_ALIGN_MARK(mark) u8 mark[0] __attribute__((aligned(CACHE_LINE_BYTES)))
struct example_large_s
{
CACHE_LINE_ALIGN_MARK (cacheline0);
u32 first; // align to CL
u32 data;
....
CACHE_LINE_ALIGN_MARK (cacheline1);
u64 *second; // align to second CL after the first one
....
};
Quindi il codice di asserzione di runtime sarebbe molto più facile da mantenere:
assert (offsetof (one_struct, cacheline0) == 0);
assert (offsetof (one_struct, cacheline1) == CACHE_LINE_BYTES);
assert (offsetof (another_struct, cacheline0) == 0);
assert (offsetof (another_struct, cacheline1) == CACHE_LINE_BYTES);