Innym zastosowaniem tablicy o zerowej długości jest nazwana etykieta wewnątrz struktury, aby pomóc w sprawdzaniu przesunięcia struktury w czasie kompilacji.
Załóżmy, że masz kilka dużych definicji struktur (obejmujących wiele linii pamięci podręcznej), które chcesz mieć pewność, że są wyrównane do granicy linii pamięci podręcznej zarówno na początku, jak iw środku, gdzie przecina granicę.
struct example_large_s
{
u32 first; // align to CL
u32 data;
....
u64 *second; // align to second CL after the first one
....
};
W kodzie możesz zadeklarować je używając rozszerzeń GCC takich jak:
__attribute__((aligned(CACHE_LINE_BYTES)))
Ale nadal chcesz się upewnić, że jest to wymuszane w czasie wykonywania.
ASSERT (offsetof (example_large_s, first) == 0);
ASSERT (offsetof (example_large_s, second) == CACHE_LINE_BYTES);
To działałoby dla pojedynczej struktury, ale byłoby trudno objąć wiele struktur, z których każda ma inną nazwę elementu członkowskiego do wyrównania. Najprawdopodobniej otrzymasz kod podobny do poniższego, w którym musisz znaleźć nazwy pierwszego członka każdej struktury:
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);
Zamiast iść w ten sposób, możesz zadeklarować w strukturze tablicę o zerowej długości, działającą jako nazwana etykieta ze spójną nazwą, ale nie zajmującą żadnej spacji.
#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
....
};
Wtedy kod asercji środowiska uruchomieniowego byłby znacznie łatwiejszy w utrzymaniu:
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);