본문 바로가기

분류대기

[C++] struct byte align

[1. 개요]

구조체 작성 시, 메모리 접근 및 구조체 크기 개선을 위한 byte align 관련 하여 정리한다.


[2. 예제]

#include <iostream>

struct A {
    char a;    // 1byte
    int b;     // 5byte
    char c[2]; // 7byte
};

struct B {
    char a;   // 1byte
    int b;    // 5byte
    char c;   // 6byte
};

struct C {
    char a;   // 1byte
    char c;   // 2byte
    int b;    // 6byte
};

struct AA {
    char a;    // 1byte
    char c[2]; // 3byte
    int b;     // 7byte
};

int main()
{
    std::cout << sizeof(A) << std::endl;
    // output is "12"
    
    std::cout << sizeof(B) << std::endl;
    // output is "12"
    
    std::cout << sizeof(C) << std::endl;
    // output is "8"

    std::cout << sizeof(AA) << std::endl;
    // output is "8"

    return 0;
}

 

구조체 안에서 변수 하나는 4byte 단위로 할당되려고 한다.

struct A 에서

  • char a 는 1byte 가 할당 된다.
  • int b 는 4byte 를 할당 받는데, char a 뒤에 이어서 연속으로 할당 될 수 없다.
  • 그래서 char a 를 위해서 4byte 공간을 할당하지만, 그 중 1byte 만 사용하는 것이다. (3byte 가 padding 됨)

그래서, 같은 멤버 구성이지만, struct B 와 struct C 의 크기가 다른 것이다.


[3. #pragma pack]

의도한만큼의 공간을 사용하려면, #pragma pack 을 이용하여 강제할 수 있다.

#include <iostream>

#pragma pack(push, 1)
// #pragma pack(push, 2)
// #pragma pack(push, 4)
// #pragma pack(push, 8)
// #pragma pack(push, 16)
struct A {
    char a;    // 1byte
    int b;     // 5byte
    char c[2]; // 7byte
};

struct B {
    char a;   // 1byte
    int b;    // 5byte
    char c;   // 6byte
};

struct C {
    char a;   // 1byte
    char c;   // 2byte
    int b;    // 6byte
};

struct AA {
    char a;    // 1byte
    char c[2]; // 3byte
    int b;     // 7byte
};
#pragma pack(pop)

int main()
{
    std::cout << sizeof(A) << std::endl;
    std::cout << sizeof(B) << std::endl;
    std::cout << sizeof(C) << std::endl;
    std::cout << sizeof(AA) << std::endl;

    return 0;
}

 

#pragma pack(push, 1)

  • 현재 메모리 정렬 방식을 스택에 푸쉬하고, 1byte 단위로 정렬한다.

#prgma pack(pop)

  • 이전에 푸쉬한 메모리 정렬 방식을 복원한다.

구조체 크기를 줄여서, 전체 메모리 사용량을 줄일 순 있으나, 

경우에 따라서는 메모리 접근 상 성능에 영향을 줄 수 있다.

  • 메모리가 정렬되지 않으면 CPU는 메모리 접근 시 추가적인 작업을 해야 할 수 있으며, 이로 인해 성능이 저하될 수 있다. 
  • 예를 들어, 4바이트 크기의 데이터가 4바이트 경계가 아닌 곳에 배치되면 CPU는 두 번의 메모리 접근을 해야 할 수도 있다.
  • 특정 아키텍처에서는 정렬되지 않은 데이터에 접근하려고 할 때 segmentation fault 가 발생 할 수 있다.

[4. 결론]

전체 메모리 사용량과 성능 사이에 tradeoff 를 고려하여 구조체를 작성하되,

가급적 4바이트 단위로 align 되는 방향으로 작성하는 것이 좋다.

 

특히, char 나 short 자료형 사용 시 주의하도록..