Інше використання масиву нульової довжини є назначеною міткою всередині структури для сприяння компіляції перевірки зміщення структури структури.
Припустимо, у вас є кілька великих структурних визначень (охоплює кілька ліній кеша), які ви хочете переконатися, що вони вирівняні до межі лінії кешу як на початку, так і в середині, де вона перетинає межу.
struct example_large_s
{
u32 first; // align to CL
u32 data;
....
u64 *second; // align to second CL after the first one
....
};
У коді ви можете оголосити їх за допомогою розширень GCC типу:
__attribute__((aligned(CACHE_LINE_BYTES)))
Але ви все ще хочете переконатися, що це виконується під час виконання.
ASSERT (offsetof (example_large_s, first) == 0);
ASSERT (offsetof (example_large_s, second) == CACHE_LINE_BYTES);
Це працювало б для однієї структури, але важко було б охопити багато структур, кожна з яких має інше ім'я члена, яке слід вирівняти. Ви, швидше за все, отримаєте код, як нижче, де ви повинні знайти імена першого члена кожної структури:
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);
Замість того, щоб піти цим шляхом, ви можете оголосити масив нульової довжини в структурі, що виступає як названа мітка з послідовною назвою, але не займає жодного місця.
#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
....
};
Тоді код твердження для виконання буде набагато простішим у підтримці:
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);