맞춤
C++의 하위 수준 기능 중 하나는 특정 하드웨어 아키텍처를 최대한 활용하기 위해 메모리 내 개체의 정확한 맞춤을 지정하는 기능입니다. 기본적으로 컴파일러는 클래스 및 구조체 멤버의 크기 값 bool
char
과 1 바이트 경계, short
2 바이트 경계, long
float
int
4 바이트 경계 및 long double
long long
double
8 바이트 경계에 정렬합니다.
대부분의 시나리오에서는 기본 맞춤이 이미 최적이므로 맞춤에 신경 쓰지 않아도 됩니다. 그러나 경우에 따라 데이터 구조에 대한 사용자 지정 맞춤을 지정하여 상당한 성능 향상 또는 메모리 절감을 달성할 수 있습니다. Visual Studio 2015 이전에는 Microsoft 관련 키워드(keyword) __alignof
__declspec(align)
사용하고 기본값보다 큰 맞춤을 지정할 수 있습니다. Visual Studio 2015부터 최대 코드 이식성을 위해 C++11 표준 키워드(keyword) alignof
alignas
사용해야 합니다. 새 키워드(keyword) Microsoft 특정 확장과 동일한 방식으로 작동합니다. 이러한 확장에 대한 설명서는 새 키워드(keyword) 적용됩니다. 자세한 내용은 연산자, alignas
지정자 및 맞춤을 참조 alignof
하세요. C++ 표준은 대상 플랫폼의 컴파일러 기본값보다 작은 경계 맞춤에 대한 압축 동작을 지정하지 않으므로 이 경우 Microsoft #pragma pack
를 사용해야 합니다.
사용자 지정 맞춤을 사용하여 데이터 구조의 메모리 할당에 aligned_storage 클래스 를 사용합니다. aligned_union 클래스는 비휘발성 생성자 또는 소멸자를 사용하는 공용 구조체에 대한 맞춤을 지정하기 위한 것입니다.
맞춤 및 메모리 주소
맞춤은 숫자 주소 모듈로 2의 거듭제곱으로 표현된 메모리 주소의 속성입니다. 예를 들어 주소 0x0001103F 모듈로 4는 3입니다. 해당 주소는 4n+3에 맞춰진 것으로, 여기서 4는 선택한 2의 힘을 나타냅니다. 주소의 맞춤은 선택한 2의 힘에 따라 달라집니다. 동일한 주소의 모듈로 8은 7입니다. 맞춤이 Xn+0인 경우 주소가 X에 맞춰집니다.
CPU는 메모리에 저장된 데이터에 대해 작동하는 명령을 실행합니다. 데이터는 메모리의 주소로 식별됩니다. 단일 데이텀의 크기도 있습니다. 주소가 크기에 맞춰지면 자연스럽게 정렬된 데이텀을 호출합니다. 그렇지 않으면 잘못 정렬되었다고 합니다. 예를 들어 8바이트 부동 소수점 데이텀은 식별에 사용되는 주소에 8바이트 맞춤이 있는 경우 자연스럽게 정렬됩니다.
데이터 맞춤의 컴파일러 처리
컴파일러는 데이터 정렬을 방해하는 방식으로 데이터 할당을 시도합니다.
단순 데이터 형식의 경우 컴파일러에서 데이터 형식 크기(바이트)의 배수인 주소를 할당합니다. 예를 들어 컴파일러는 주소의 하위 2 비트를 0으로 설정하여 4의 배수인 형식 long
의 변수에 주소를 할당합니다.
또한 컴파일러는 구조체의 각 요소를 자연스럽게 맞추는 방식으로 구조체를 패딩합니다. 다음 코드 예제의 구조를 struct x_
고려합니다.
struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} bar[3];
컴파일러는 자연스럽게 맞춰지도록 이 구조를 채웁니다.
다음 코드 예제에서는 컴파일러가 패딩된 구조를 메모리에 배치하는 방법을 보여 줍니다.
// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
} bar[3];
두 선언 모두 12바이트로 반환 sizeof(struct x_)
됩니다.
두 번째 선언에는 다음 두 개의 패딩 요소가 포함되어 있습니다.
char _pad0[3]
4 바이트 경계에 멤버를 정렬int b
합니다.char _pad1[1]
구조체의struct _x bar[3];
배열 요소를 4 바이트 경계에 맞추려면
안쪽 여백은 자연 액세스를 허용하는 방식으로 요소를 bar[3]
정렬합니다.
다음 코드 예제에서는 배열 레이아웃을 bar[3]
보여줍니다.
adr offset element
------ -------
0x0000 char a; // bar[0]
0x0001 char pad0[3];
0x0004 int b;
0x0008 short c;
0x000a char d;
0x000b char _pad1[1];
0x000c char a; // bar[1]
0x000d char _pad0[3];
0x0010 int b;
0x0014 short c;
0x0016 char d;
0x0017 char _pad1[1];
0x0018 char a; // bar[2]
0x0019 char _pad0[3];
0x001c int b;
0x0020 short c;
0x0022 char d;
0x0023 char _pad1[1];
alignof
및 alignas
alignas
지정자는 변수 및 사용자 정의 형식의 사용자 지정 맞춤을 지정하는 이식 가능한 C++ 표준 방법입니다. alignof
마찬가지로 연산자는 지정된 형식 또는 변수의 맞춤을 가져오는 표준 이식 가능한 방법입니다.
예시
클래스, 구조체 또는 공용 구조체 또는 개별 멤버에서 사용할 alignas
수 있습니다. 여러 alignas
지정자가 발견되면 컴파일러는 값이 가장 큰 지정자를 선택합니다.
// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
alignas(4) char arr[3];
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
참고 항목
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기