길이가 0 인 배열의 또 다른 용도는 컴파일 시간 구조체 오프셋 검사를 지원하기 위해 구조체 내부의 명명 된 레이블로 사용하는 것입니다.
(여러 캐시 라인에 걸쳐있는) 큰 구조체 정의가 경계를 넘는 시작 부분과 중간 부분 모두에서 캐시 라인 경계에 정렬되도록하고 싶다고 가정합니다.
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);
이런 식으로하는 대신, 일관된 이름을 가진 명명 된 레이블 역할을하지만 공간을 소비하지 않는 구조에서 길이가 0 인 배열을 선언 할 수 있습니다.
#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);