__declspec(align(#))
를 사용하여 사용자 정의 데이터(예: 함수의 정적 할당 또는 자동 데이터)를 정확하게 제어합니다.
__declspec( align( # ) ) declarator
최신 프로세서 명령을 사용하는 응용 프로그램을 작성할 경우 몇 가지 새로운 제약 조건과 문제가 생깁니다. 특히 새로운 명령을 사용할 때 데이터를 16바이트 경계에 맞춰야 하는 경우가 많습니다. 또한 자주 사용하는 데이터를 특정 프로세서의 캐시 줄 크기에 맞춤으로써 캐시 성능이 향상됩니다. 예를 들어 크기가 32바이트 미만인 구조체를 정의할 경우 해당 구조체 형식의 개체가 효과적으로 캐시되도록 이 구조체를 32바이트에 맞출 수 있습니다.
#은 맞춤 값입니다. 유효한 항목은 2, 4, 8, 16, 32 또는 64와 같이 1에서 8192(바이트) 사이에 속하는 2의 정수 제곱입니다. declarator
는 aligned로 선언하는 데이터입니다.
형식의 맞춤 요구 사항인 size_t
형식의 값을 반환하는 방법에 대한 자세한 내용은 __alignof를 참조하고 64비트 프로세서를 대상으로 하는 경우 정렬되지 않은 포인터를 선언하는 방법은 __unaligned를 참조하세요.
__declspec(align(#))
, struct
또는 union
를 정의하거나 변수를 선언할 때 class
를 사용할 수 있습니다.
컴파일러는 복사 또는 데이터 변환 작업 중에 데이터의 맞춤 특성 보존을 보장하거나 시도하지 않습니다. 예를 들어 memcpy는 __declspec(align(#))
로 선언된 구조체를 임의의 위치에 복사할 수 있습니다. malloc, C++ operator new 및 Win32 할당자와 같은 일반 할당자가 반환하는 메모리는 대개 __declspec(align(#))
구조체 또는 구조체 배열에 사용할 수 있도록 충분히 맞춰지지 않은 상태입니다. 복사 또는 데이터 변환 작업의 대상이 올바르게 맞춰지도록 하려면 _aligned_malloc를 사용하거나 할당자를 직접 작성합니다.
함수 매개 변수의 맞춤을 지정할 수 없습니다. 맞춤 특성을 포함하는 데이터가 스택의 값에 의해 전달되면 해당 맞춤은 호출 규칙을 통해 제어됩니다. 호출된 함수에서 데이터 맞춤이 중요한 경우에는 사용 전에 매개 변수를 올바르게 맞춰진 메모리로 복사합니다.
__declspec(align(#))
를 사용하지 않는 경우 Visual C++는 일반적으로 대상 프로세서와 데이터 크기를 기반으로 자연 경계에 데이터를 맞춥니다(32비트 프로세서에서는 최대 4바이트 경계, 64비트 프로세서에서는 최대 8바이트 경계). 클래스 또는 구조체의 데이터는 최소한의 자연 맞춤 및 현재의 압축 설정(#pragma pack
또는 /Zp 컴파일러 옵션에서)으로 클래스나 구조체에 맞춰집니다.
이 예제에서는 __declspec(align(#))
의 사용을 보여 줍니다.
__declspec(align(32)) struct Str1{ int a, b, c, d, e; };
현재 이 형식에는 32비트 맞춤 특성이 포함되어 있습니다. 즉, 모든 정적 및 자동 인스턴스가 32바이트 경계에서 시작됩니다. 이 형식을 사용하여 멤버로 선언된 추가 구조체 형식은 이 형식의 맞춤 특성을 유지하여 Str1
이 요소로 지정된 모든 구조체는 32 이상의 맞춤 특성을 갖게 됩니다.
sizeof(struct Str1)
는 32입니다. 즉, Str1 개체 배열을 만드는 경우 배열의 기준을 32바이트로 맞추면 배열의 각 멤버도 32바이트로 맞춰집니다. 동적 메모리에서 기준이 올바르게 맞춰진 배열을 만들려면 _aligned_malloc를 사용하거나 할당자를 직접 작성합니다.
구조체의 sizeof
값은 최종 멤버의 오프셋에 해당 멤버의 크기를 더하여 최대 멤버 맞춤 값 또는 전체 구조체 맞춤 값 중 더 큰 값의 가장 근사한 배수로 반올림한 값입니다.
컴파일러는 구조체 맞춤에 다음과 같은 규칙을 사용합니다.
__declspec(align(#))
로 재정의하지 않으면 스칼라 구조체 멤버의 맞춤은 최소 크기와 현재 압축입니다.__declspec(align(#))
로 재정의하지 않으면 구조체의 멤버는 멤버의 최대 개별 맞춤입니다.구조체 멤버는 이전 멤버 끝의 오프셋보다 크거나 같은 맞춤의 최소 배수인 부모 구조체의 시작 부분부터 오프셋에 배치됩니다.
구조체의 크기는 마지막 멤버의 오프셋 끝보다 크거나 같은 맞춤의 최소 배수입니다.
__declspec(align(#))
는 맞춤 제한만 늘릴 수 있습니다.
맞춤 (C++)
Visual Studio 2017 에 대한 최신 설명서는 Visual Studio 2017 설명서를 참조하세요.
Visual Studio 2015 이상 버전에서는 C++11 표준 alignas
지정자를 사용하여 맞춤을 제어합니다. 자세한 내용은 맞춤을 참조하세요.
Microsoft 전용
__declspec(align(#))
를 사용하여 사용자 정의 데이터(예: 함수의 정적 할당 또는 자동 데이터)를 정확하게 제어합니다.
__declspec( align( # ) ) declarator
최신 프로세서 명령을 사용하는 응용 프로그램을 작성할 경우 몇 가지 새로운 제약 조건과 문제가 생깁니다. 특히 새로운 명령을 사용할 때 데이터를 16바이트 경계에 맞춰야 하는 경우가 많습니다. 또한 자주 사용하는 데이터를 특정 프로세서의 캐시 줄 크기에 맞춤으로써 캐시 성능이 향상됩니다. 예를 들어 크기가 32바이트 미만인 구조체를 정의할 경우 해당 구조체 형식의 개체가 효과적으로 캐시되도록 이 구조체를 32바이트에 맞출 수 있습니다.
#은 맞춤 값입니다. 유효한 항목은 2, 4, 8, 16, 32 또는 64와 같이 1에서 8192(바이트) 사이에 속하는 2의 정수 제곱입니다. declarator
는 aligned로 선언하는 데이터입니다.
형식의 맞춤 요구 사항인 size_t
형식의 값을 반환하는 방법에 대한 자세한 내용은 __alignof를 참조하고 64비트 프로세서를 대상으로 하는 경우 정렬되지 않은 포인터를 선언하는 방법은 __unaligned를 참조하세요.
__declspec(align(#))
, struct
또는 union
를 정의하거나 변수를 선언할 때 class
를 사용할 수 있습니다.
컴파일러는 복사 또는 데이터 변환 작업 중에 데이터의 맞춤 특성 보존을 보장하거나 시도하지 않습니다. 예를 들어 memcpy는 __declspec(align(#))
로 선언된 구조체를 임의의 위치에 복사할 수 있습니다. malloc, C++ operator new 및 Win32 할당자와 같은 일반 할당자가 반환하는 메모리는 대개 __declspec(align(#))
구조체 또는 구조체 배열에 사용할 수 있도록 충분히 맞춰지지 않은 상태입니다. 복사 또는 데이터 변환 작업의 대상이 올바르게 맞춰지도록 하려면 _aligned_malloc를 사용하거나 할당자를 직접 작성합니다.
함수 매개 변수의 맞춤을 지정할 수 없습니다. 맞춤 특성을 포함하는 데이터가 스택의 값에 의해 전달되면 해당 맞춤은 호출 규칙을 통해 제어됩니다. 호출된 함수에서 데이터 맞춤이 중요한 경우에는 사용 전에 매개 변수를 올바르게 맞춰진 메모리로 복사합니다.
__declspec(align(#))
를 사용하지 않는 경우 Visual C++는 일반적으로 대상 프로세서와 데이터 크기를 기반으로 자연 경계에 데이터를 맞춥니다(32비트 프로세서에서는 최대 4바이트 경계, 64비트 프로세서에서는 최대 8바이트 경계). 클래스 또는 구조체의 데이터는 최소한의 자연 맞춤 및 현재의 압축 설정(#pragma pack
또는 /Zp 컴파일러 옵션에서)으로 클래스나 구조체에 맞춰집니다.
이 예제에서는 __declspec(align(#))
의 사용을 보여 줍니다.
__declspec(align(32)) struct Str1{ int a, b, c, d, e; };
현재 이 형식에는 32비트 맞춤 특성이 포함되어 있습니다. 즉, 모든 정적 및 자동 인스턴스가 32바이트 경계에서 시작됩니다. 이 형식을 사용하여 멤버로 선언된 추가 구조체 형식은 이 형식의 맞춤 특성을 유지하여 Str1
이 요소로 지정된 모든 구조체는 32 이상의 맞춤 특성을 갖게 됩니다.
sizeof(struct Str1)
는 32입니다. 즉, Str1 개체 배열을 만드는 경우 배열의 기준을 32바이트로 맞추면 배열의 각 멤버도 32바이트로 맞춰집니다. 동적 메모리에서 기준이 올바르게 맞춰진 배열을 만들려면 _aligned_malloc를 사용하거나 할당자를 직접 작성합니다.
구조체의 sizeof
값은 최종 멤버의 오프셋에 해당 멤버의 크기를 더하여 최대 멤버 맞춤 값 또는 전체 구조체 맞춤 값 중 더 큰 값의 가장 근사한 배수로 반올림한 값입니다.
컴파일러는 구조체 맞춤에 다음과 같은 규칙을 사용합니다.
__declspec(align(#))
로 재정의하지 않으면 스칼라 구조체 멤버의 맞춤은 최소 크기와 현재 압축입니다.__declspec(align(#))
로 재정의하지 않으면 구조체의 멤버는 멤버의 최대 개별 맞춤입니다.구조체 멤버는 이전 멤버 끝의 오프셋보다 크거나 같은 맞춤의 최소 배수인 부모 구조체의 시작 부분부터 오프셋에 배치됩니다.
구조체의 크기는 마지막 멤버의 오프셋 끝보다 크거나 같은 맞춤의 최소 배수입니다.
__declspec(align(#))
는 맞춤 제한만 늘릴 수 있습니다.
자세한 내용은 다음을 참조하세요.
구조체 맞춤 예제(x64 전용)
다음 예제에서는 __declspec(align(#))
가 데이터 구조체의 크기 및 맞춤에 영향을 주는 방식을 보여 줍니다. 예제에서는 다음과 같은 정의를 가정합니다
#define CACHE_LINE 32 #define CACHE_ALIGN __declspec(align(CACHE_LINE))
이 예제에서는 S1
를 사용하여 __declspec(align(32))
구조체를 정의합니다. 변수 정의에 대해 또는 기타 형식 선언에서 사용되는 모든 S1
은 32바이트로 맞춰집니다. sizeof(struct S1)
는 32를 반환하고 S1
은 16바이트 뒤에 정수 4개에 필요한 16 패딩 바이트를 둡니다. 각 int
멤버는 4바이트로 맞춰야 하지만 구조체 자체의 맞춤은 32로 선언됩니다. 따라서 전체 맞춤은 32입니다.
struct CACHE_ALIGN S1 { // cache align all instances of S1 int a, b, c, d; }; struct S1 s1; // s1 is 32-byte cache aligned
이 예제에서는 최대 맞춤 요구 사항의 배수가 8의 배수인 16이므로 sizeof(struct S2)
는 멤버 크기의 합계와 똑같은 16을 반환합니다.
__declspec(align(8)) struct S2 { int a, b, c, d; };
다음 예제에서 sizeof(struct S3)
는 64를 반환합니다.
struct S3 { struct S1 s1; // S3 inherits cache alignment requirement // from S1 declaration int a; // a is now cache aligned because of s1 // 28 bytes of trailing padding };
이 예제에서 a
에는 자연 형식 맞춤(여기서는 4바이트)이 사용됩니다. 그러나 S1
은 32바이트 맞춤이어야 합니다. 28바이트 패딩이 a
뒤에 나와 s1
이 32 오프셋에서 시작됩니다. 그런 다음 S4
가 구조체의 최대 맞춤 요구 사항인 S1
의 맞춤 요구 사항을 상속합니다. sizeof(struct S4)
가 64를 반환합니다.
struct S4 { int a; // 28 bytes padding struct S1 s1; // S4 inherits cache alignment requirement of S1 };
다음 3개의 변수 선언에도 __declspec(align(#))
가 사용됩니다. 각 선언에서 변수가 32바이트 맞춤이어야 합니다. 배열의 경우 각 배열 멤버가 아니라 배열의 기준 주소가 32바이트 맞춤입니다. sizeof
를 사용해도 각 배열 멤버의 __declspec(align(#))
값에 영향을 주지 않습니다.
CACHE_ALIGN int i; CACHE_ALIGN int array[128]; //배열의 경우에 32 바이트단위로 맞춤(끊어)정렬된다 CACHE_ALIGN struct s2 s;
배열의 각 멤버를 맞추려면 다음과 같은 코드를 사용해야 합니다.
typedef CACHE_ALIGN struct { int a; } S5; S5 array[10];
'프로그래밍(Programming) > c++, 11, 14 , 17, 20' 카테고리의 다른 글
메모리관점에서 본 전역(global)변수와 정적(static)변수의 차이 (0) | 2018.02.16 |
---|---|
레지스터와 연산 처리과정 EAX, EDX, ECX, EBX, ESI, EDI, ESI, EDI (0) | 2018.02.13 |
__attribute__ ((noinline)) (0) | 2017.05.14 |
상속의 복사생성자 (0) | 2016.11.06 |
클로져 객체의 복사 생성자와 소멸자 (0) | 2016.07.18 |