포스트

[C++] 바이트 패딩

[C++] 바이트 패딩

바이트 패딩(Byte Padding)과 정렬(Alignment)

C/C++에서 구조체를 정의할 때 성능과 하드웨어 요구 사항을 만족시키기 위해, 메모리 정렬(Alignment)바이트 패딩(Byte Padding) 개념이 사용됩니다. 이 문서는 바이트 패딩의 개념, 동작 원리, 그리고 32비트/64비트 아키텍처와의 관계까지 정리합니다.


1. 바이트 패딩이란?

바이트 패딩(Byte Padding)은 정렬을 맞추기 위해 삽입되는 여분의 바이트입니다. CPU가 데이터를 효율적으로 읽기 위해 특정 타입의 데이터를 주소 경계(alignment boundary) 에 맞게 배치해야 합니다.

예시 1

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

struct A {
    char a;   // 1 byte
    int b;    // 4 bytes
};

int main() {
    std::cout << "sizeof(A): " << sizeof(A) << std::endl;  // 결과: 8
    return 0;
}
  • char a는 주소 0x1000에 배치
  • int b는 4바이트 정렬을 요구 → 주소 0x1004에 배치
  • 사이 0x1001~0x1003 → 패딩 3바이트 삽입

시각화 (메모리 구성도)

1
2
3
4
주소     값        설명
0x1000   a         char a (1 byte)
0x1001   (pad)     padding (3 bytes)
0x1004   b         int b (4 bytes)

총 크기: 8바이트


2. 정렬되지 않은 데이터란?

정렬되지 않은 데이터(Unaligned Data) 란, 데이터가 자신의 정렬 기준에 맞지 않는 주소에 저장된 경우입니다.

예: int는 4바이트 정렬을 요구하는데, 주소 0x1003에 저장되면 → 정렬되지 않음 → CPU는 처리에 시간이 오래 걸리거나 예외 발생

정렬이 필요한 이유는 다음과 같습니다:

  • CPU는 메모리를 4/8 바이트 단위로 읽음
  • 정렬된 주소에 있어야 한 번에 빠르게 읽을 수 있음
  • 정렬되지 않으면 두 번 접근하거나 오류 발생 가능

예시 2: 정렬되지 않은 데이터 접근 (x86 일부 환경에서 오류 발생 가능)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma pack(1)
struct Unaligned {
    char c;
    int i;
};

int main() {
    Unaligned u;
    u.c = 'x';
    u.i = 12345;  // 주소 정렬이 안 되어 있을 수 있음

    std::cout << u.i << std::endl;  // 일부 시스템에서는 느려지거나 예외 발생
    return 0;
}

시각화

1
2
3
주소     값
0x1000   c ('x')
0x1001   i (12345, 4 bytes) → 비정렬 상태

총 크기: 5바이트 (정렬 위반)


3. 구조체 내 정렬 기준

  • 구조체의 전체 정렬 기준은 가장 큰 멤버의 정렬 단위에 맞춰짐
  • 예: char(1B), double(8B) → 구조체 정렬 기준은 8바이트

예시 3: 정렬 기준에 따른 크기 변화

1
2
3
4
5
6
7
8
9
10
struct B {
    char a;   // 1 byte
    double b; // 8 byte
    int c;    // 4 byte
};

int main() {
    std::cout << "sizeof(B): " << sizeof(B) << std::endl;  // 결과: 24 (플랫폼에 따라 다를 수 있음)
    return 0;
}

시각화

1
2
3
4
5
6
주소     값
0x1000   a (1 byte)
0x1001   (pad x7)
0x1008   b (8 bytes)
0x1010   c (4 bytes)
0x1014   (pad x4) → 구조체 전체 정렬(8B)에 맞추기 위해

총 크기: 24바이트


4. 바이트 패딩 최소화 방법

방법 1: 멤버 순서 변경

1
2
3
4
5
6
7
8
9
10
11
// Before
struct A {
    char a;
    int b;
};

// After
struct A {
    int b;
    char a;
};

방법 2: 컴파일러 지시어 사용

1
2
3
4
5
6
7
8
9
10
#pragma pack(1)
struct Packed {
    char a;
    int b;
};

int main() {
    std::cout << sizeof(Packed) << std::endl;  // 결과: 5
    return 0;
}

시각화 (Packed 구조체)

1
2
3
주소     값
0x1000   a (1 byte)
0x1001   b (4 bytes) → 비정렬 상태

총 크기: 5바이트

주의: 성능 저하, CPU 예외 가능성 있음


5. 정렬과 바이트 패딩 비교

개념설명
정렬 (Alignment)특정 타입이 특정 주소 경계에 배치되도록 강제하는 규칙
패딩 (Padding)정렬을 맞추기 위해 삽입되는 빈 공간

6. 32비트 vs 64비트 시스템과의 관계

항목32비트 시스템64비트 시스템
주소 버스32비트 (4GB)64비트 (확장된 주소 공간)
포인터 크기4바이트8바이트
정렬 기준주로 4바이트주로 8바이트
패딩 발생상대적으로 적음상대적으로 많을 수 있음

예시 4: 플랫폼별 구조체 비교

1
2
3
4
5
6
7
8
9
10
struct Example {
    char c;
    int i;
    double d;
};

int main() {
    std::cout << "sizeof(Example): " << sizeof(Example) << std::endl;
    return 0;
}
  • 32비트 시스템: 구조체 크기 = 20바이트 (중간 패딩 있음)
  • 64비트 시스템: 구조체 크기 = 24바이트 (정렬 기준 증가, 더 많은 패딩)

7. 요약

  • 바이트 패딩은 CPU의 정렬 요구를 충족하기 위해 삽입되는 빈 공간
  • 정렬되지 않은 데이터는 성능 저하 및 오류 유발 가능
  • 구조체의 멤버 순서 변경, pack 지시어 사용으로 패딩을 줄일 수 있음
  • 32비트와 64비트 시스템은 정렬 기준과 구조체 크기에 영향을 줌
  • 실험 코드를 통해 구조체의 실제 크기를 확인할 수 있으며, 플랫폼에 따라 결과는 다르게 나타남
  • 시각화 예제를 통해 구조체의 메모리 배치와 패딩 상황을 직관적으로 이해할 수 있음
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.