C++(MSVC)의 alignment 지정자간의 차이

JellyPower·2023년 9월 8일
0

나만 몰랐던 C++

목록 보기
8/11
post-thumbnail
  • msvc는 #pragma pack(n)키워드를 통해 프로그래머가 데이터 alignment 단위를 지정해 줄 수 있다.
  • 그런데 msdn을 보면

Visual Studio 2015 이상에서는 __alignof __declspec( align ) 키워드와 같이 msvc전용 키워드가 아닌, 컴파일러 간에 이식 가능한 표준 alignas alignof 연산자를 사용 할 수 있습니다. 그러나, C++ 표준은 packing을 처리하지 않으므로 대상 아키텍처의 word size보다 작은 align을 지정하려면 #pragma pack(n) (또는 컴파일러마다 가지는 확장 키워드)를 계속 사용해야 합니다.

  • 라고 적혀있다.

Pack의 특징

  • msvc가 #pragma pack키워드를 지원하는 이유는 데이터 얼라인을 맞추기 위함이 맞긴 하지만, 더 정확히 말하자면 데이터 얼라인을 프로그래머가 임의로 조정하여 데이터를 "압축"하는 것을 위한 것이다.
  • 직접 정의한 구조체, 클래스가 자동으로 생성한 default alignment사이즈보 작은 alignment를 허용하게 하기 위해 사용된다는 것이다.
  • 즉, 자동으로 생성한 alignment사이즈보다 pack을 통해 alignment하려는 사이즈가 더 크다면 압축이 되지 않는다. 아래의 예제를 보자.
#pragma pack(8)
struct MyData {
    char a;
    float b;
    char c;
};
int main(){
    printf("%d", sizeof(MyData));
}
  • 8바이트로 align한다는 관점에선 16바이트가 나와야 될 것 같지만 실상은 12바이트가 나온다.

  • #pragma pack(n)은 "압축"을 위한 것이기 때문에 default로 지정된 4byte기준이 유저가 지정한 8byte보다 커서 4byte패딩을 진행하여 12바이트가 나오는 것이다.

    💡 default alignment규칙은 상황에따라 다르지만 위와 같이 구조체를 정의하는 경우 구조체 내의 가장 큰 데이터 타입으로 align을 진행한다. 위의 경우에 가장 큰 데이터 타입이 4byte float이므로 4byte align이다.

alignas의 특징

  • 그렇기에 데이터를 packing하는 것이 아니라 단순히 alignment 용도라면__declspec(align(n)) 같은 msvc전용 키워드나 alignas(n)같은 표준 연산자를 사용하는 것이 옳다.

#pragma pack(8)
struct MyData {
    char a;
    float b;
    char c;
};
// sizeof(MyData): 12
// alignof(MyData): 4

__declspec(align(8))
struct MyData {
    char a;
    float b;
    char c;
};
// sizeof(MyData): 16
// alignof(MyData): 8

struct alignas(8) MyData {
    char a;
    float b;
    char c;
};
// sizeof(MyData): 16
// alignof(MyData): 8

근데! 여기서 또 주의해야 할 점은 위 msdn설명에 나와있듯 “C++ 표준은 packing을 처리하지 않”기 때문에 #pragma pack(1)과 같이 더 작은 사이즈로 데이터를 “압축”하는 용도에선 __declspec(align(n)), alignas(n)연산자가 먹히지 않는다.

#pragma pack(1)
struct MyData {
    char a;
    float b;
    char c;
};
// sizeof(MyData): 6
// alignof(MyData): 1

__declspec(align(1))
struct MyData {
    char a;
    float b;
    char c;
};
// sizeof(MyData): 12
// alignof(MyData): 4

struct alignas(1) MyData {
    char a;
    short b;
    char c;
};
// default보다 더 작은 값으로 align을 진행하려 했다고 error를 던져줌

결론

  • default alignment size보다 더 작은 단위로 진행하는 alignment는
    • #pragma pack(n)을 사용하고
  • default alignment size보다 더 큰 단위로 진행하는 alignment는
    • __declspec(align(n)), alignas(n)를 사용하자.

레퍼런스

alignas, alignof 키워드

변수의 메모리 할당과 #pragma pack()

pack pragma

profile
게임엔진코드싸개(진)

0개의 댓글