การใช้อาร์เรย์ที่มีความยาวเป็นศูนย์อีกอย่างหนึ่งคือการตั้งชื่อป้ายกำกับภายในโครงสร้างเพื่อช่วยในการคอมไพล์การตรวจสอบการชดเชยโครงสร้างเวลา
สมมติว่าคุณมีคำจำกัดความของโครงสร้างขนาดใหญ่ (ครอบคลุมบรรทัดแคชหลายบรรทัด) ที่คุณต้องการตรวจสอบให้แน่ใจว่ามีการจัดแนวให้ตรงกับขอบเขตบรรทัดแคชทั้งในจุดเริ่มต้นและตรงกลางโดยที่มันข้ามขอบเขต
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);