`_Alignas`/`alignas` 정렬 지정자
_Alignas/alignas 정렬 지정자
어떤 객체를 메모리에서 더 큰 정렬 경계에 배치하고 싶을 때가 있어요. 예를 들어 캐시라인 단위로 정렬된 배열을 만들고 싶다거나요. 그럴 때 선언 구문에서 타입 지정자 자리에 붙여서 객체의 정렬 요구(alignment requirement)를 바꿔주는 게 _Alignas(C23부터는 alignas) 지정자예요.
출처: cppreference
본문
_Alignas(C23 이후는 alignas)는 선언되는 객체의 정렬 요구를 수정하는 타입 지정자 중 하나로 선언 구문에 등장해요.
문법
_Alignas ( expression ) |
(1) | (since C11) |
alignas ( expression ) |
(2) | (since C23) |
_Alignas ( type ) |
(3) | (since C11) |
alignas ( type ) |
(4) | (since C23) |
expression |
- | 값이 유효한 정렬이거나 0인 정수 상수 표현식 |
type |
- | 아무 타입 이름 |
참고: C23 이전에는
_Alignas키워드가<stdalign.h>헤더의 편의 매크로alignas로도 쓸 수 있었어요.
설명
_Alignas(C23 이후 alignas) 지정자는 비트필드가 아니면서 register 저장소 클래스를 갖지 않는 객체를 선언할 때만 쓸 수 있어요. 함수 매개변수 선언에는 쓸 수 없고, typedef에도 쓸 수 없어요.
선언에서 이 지정자를 쓰면, 선언되는 객체의 정렬 요구는 다음과 같이 정해져요.
1,2) expression의 값 (0이 아니면)
3,4) type의 정렬 요구, 즉 _Alignof(type)(C23 이후 alignof(type))
단, 이렇게 해서 타입이 원래 자연스럽게 가졌을 정렬보다 약해지는 경우는 예외예요. expression이 0으로 평가되면 이 지정자는 아무 효과가 없어요.
같은 선언에 _Alignas(C23 이후 alignas)가 여러 번 등장하면, 가장 엄격한(가장 큰) 것이 적용돼요.
_Alignas(C23 이후 alignas) 지정자는 객체의 정의에만 등장해도 되지만, 어떤 선언에서 이 지정자를 쓴다면 정의에서 쓴 것과 같은 정렬을 명시해야 해요. 서로 다른 번역 단위가 같은 객체에 대해 다른 정렬을 지정하면 동작은 정의되지 않아요(undefined behavior).
주의
C++에서는 alignas 지정자를 class/struct/union 타입과 열거형의 선언에도 적용할 수 있어요. C에서는 그게 지원되지 않지만, 멤버 선언에 _Alignas(C23 이후 alignas)를 써서 struct 타입의 정렬을 조절할 수는 있어요.
키워드
alignas, _Alignas
예시
struct sse_t 타입의 모든 객체를 16바이트 경계에, struct data 타입의 모든 객체를 128바이트 경계에 정렬하는 코드예요.
#include <stdalign.h>
#include <stdio.h>
// every object of type struct sse_t will be aligned to 16-byte boundary
// (note: needs support for DR 444)
struct sse_t
{
alignas(16) float sse_data[4];
};
// every object of type struct data will be aligned to 128-byte boundary
struct data
{
char x;
alignas(128) char cacheline[128]; // over-aligned array of char,
// not array of over-aligned chars
};
int main(void)
{
printf("sizeof(data) = %zu (1 byte + 127 bytes padding + 128-byte array)\n",
sizeof(struct data));
printf("alignment of sse_t is %zu\n", alignof(struct sse_t));
alignas(2048) struct data d; // this instance of data is aligned even stricter
(void)d; // suppresses "maybe unused" warning
}
출력:
sizeof(data) = 256 (1 byte + 127 bytes padding + 128-byte array)
alignment of sse_t is 16
여기서 눈여겨볼 점은 alignas(16)이 붙은 sse_data 멤버 덕분에 struct sse_t의 정렬이 16으로 잡힌다는 거예요. 또 alignas(2048)은 지역 변수 하나에 더 엄격한 정렬을 적용하는 예시죠.
결함 보고
이전 C 표준에 소급 적용된 동작 변경 결함 보고는 다음과 같아요.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| DR 444 | C11 | _Alignas는 struct/union 멤버에서 허용되지 않았음 |
허용됨 |
더 알아보기
- 객체의 정렬 요구를 읽어내는
_Alignof/alignof연산자와 짝을 이뤄요. - 정렬(alignment)의 개념과 규칙은 객체와 정렬 문서에서 더 자세히 볼 수 있어요.
- cppreference의 alignas 원문에서 결함 보고 기록을 더 확인할 수 있어요.