[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 라이센스를 따릅니다.