2016-08-09 3 views
2

가 나는 각 필드의 정렬 (비주얼 스튜디오 2015)이 구조체가 정렬 된 이유는 무엇입니까? VULKAN 헤더 <code>vulkan.h</code>에서

std::cout << 
     "sType: " << offsetof(VkSwapchainCreateInfoKHR, sType) << std::endl << 
     "pNext: " << offsetof(VkSwapchainCreateInfoKHR, pNext) << std::endl << 
     "flags: " << offsetof(VkSwapchainCreateInfoKHR, flags) << std::endl << 
     "surface: " << offsetof(VkSwapchainCreateInfoKHR, surface) << std::endl << 
     "minImageCount: " << offsetof(VkSwapchainCreateInfoKHR, minImageCount) << std::endl << 
     "imageFormat: " << offsetof(VkSwapchainCreateInfoKHR, imageFormat) << std::endl << 
     "imageColorSpace: " << offsetof(VkSwapchainCreateInfoKHR, imageColorSpace) << std::endl << 
     "imageExtent: " << offsetof(VkSwapchainCreateInfoKHR, imageExtent) << std::endl << 
     "imageArrayLayers: " << offsetof(VkSwapchainCreateInfoKHR, imageArrayLayers) << std::endl << 
     "imageUsage: " << offsetof(VkSwapchainCreateInfoKHR, imageUsage) << std::endl << 
     "imageSharingMode: " << offsetof(VkSwapchainCreateInfoKHR, imageSharingMode) << std::endl << 
     "queueFamilyIndexCount: " << offsetof(VkSwapchainCreateInfoKHR, queueFamilyIndexCount) << std::endl << 
     "pQueueFamilyIndices: " << offsetof(VkSwapchainCreateInfoKHR, pQueueFamilyIndices) << std::endl << 
     "preTransform: " << offsetof(VkSwapchainCreateInfoKHR, preTransform) << std::endl << 
     "compositeAlpha: " << offsetof(VkSwapchainCreateInfoKHR, compositeAlpha) << std::endl << 
     "presentMode: " << offsetof(VkSwapchainCreateInfoKHR, presentMode) << std::endl << 
     "clipped: " << offsetof(VkSwapchainCreateInfoKHR, clipped) << std::endl << 
     "oldSwapchain: " << offsetof(VkSwapchainCreateInfoKHR, oldSwapchain) << std::endl << 
     std::endl; 

를 보려면 다음 코드를 사용했습니다

typedef struct VkSwapchainCreateInfoKHR { 
    VkStructureType     sType; 
    const void*      pNext; 
    VkSwapchainCreateFlagsKHR  flags; 
    VkSurfaceKHR      surface; 
    uint32_t       minImageCount; 
    VkFormat       imageFormat; 
    VkColorSpaceKHR     imageColorSpace; 
    VkExtent2D      imageExtent; 
    uint32_t       imageArrayLayers; 
    VkImageUsageFlags    imageUsage; 
    VkSharingMode     imageSharingMode; 
    uint32_t       queueFamilyIndexCount; 
    const uint32_t*     pQueueFamilyIndices; 
    VkSurfaceTransformFlagBitsKHR preTransform; 
    VkCompositeAlphaFlagBitsKHR  compositeAlpha; 
    VkPresentModeKHR     presentMode; 
    VkBool32       clipped; 
    VkSwapchainKHR     oldSwapchain; 
} VkSwapchainCreateInfoKHR; 

로 정의 된 구조체이며, 이러한 결과를 얻었다

sType: 0 
pNext: 8 
flags: 16 
surface: 24 
minImageCount: 32 
imageFormat: 36 
imageColorSpace: 40 
imageExtent: 44 
imageArrayLayers: 52 
imageUsageFlags: 56 
imageSharingMode: 60 
queueFamilyIndexCount: 64 
pQueueFamilyIndices: 72 
preTransform: 80 
compositeAlpha: 84 
presentMode: 88 
clipped: 92 
oldSwapchain: 96 

필드 flagssurface 사이에는 8 바이트 간격 인 이브 n flags의 기본 유형은 uint32_t입니다. 필드가 queueFamilyIndexCountpQueueFamilyIndices 인 경우에도 마찬가지입니다. flagsqueueFamilyIndexCount은 너비가 4 바이트 일 때 8 바이트를 차지하며 uint32_t 유형의 모든 다른 필드는 4 바이트 만 차지하는 이유는 무엇입니까? 이러한 오프셋에서 메모리 정렬 요구 사항에 특별한 것이 있습니까?

+2

채우기 ......................... –

+0

그런데 왜 그 필드 만 패딩이됩니까? 둘 다 16의 배수로 오프셋되었으므로 다음 필드에 왜 패딩이 필요합니까? – rhynodegreat

+2

@ πάνταῥεῖ 그는 멋지다. :) –

답변

4

VkSurfaceKHR은 처리 할 수없는 핸들입니다. Vulkan의 정의에 따르면 64 비트 정수입니다. 따라서 8 바이트 정렬이 있어야합니다.

구조체가 배치 될 때 컴파일러는 각 멤버가 형식에 필요한 정렬을 얻도록합니다. surfaceflags 바로 뒤에 오면 8 바이트 정렬이되지 않습니다. 따라서 컴파일러는이 두 바이트 사이에 4 바이트의 패딩을 삽입합니다.

+0

문제는 'flags'가 8 바이트를 차지한다는 것입니다. – rhynodegreat

+6

@rhynodegreat : 아니에요. 그것은 4 바이트를 차지합니다. 그 다음에 4 * unusued 바이트 *가 있으므로 다음 필드는 8 바이트 정렬 될 수 있습니다. –

+1

아, 그래서 다음 필드가 8 바이트이고 정렬되어야하기 때문에 패딩이 추가됩니다. 포인터가 뒤에 오는'queueFamilyIndexCount'와 동일합니다. – rhynodegreat

1

모든 유형의 크기는 sizeof(T)이고 맞춤 요구 사항은 alignof(T)입니다. 그 인스턴스는 항상 alignof(T)의 여러 주소에 메모리에 배치되어야합니다. 구조체에서

컴파일러는 자동적으로 이러한 요건은 구조체의 선두 어드레스에 대하여 모든 요소 (즉 offsetof 값)에 대해 만족되도록 소자 사이 패딩 삽입. 이것은 후속 struct 요소 사이의 빈 공간입니다.

또한 전체 구조체의 alignof을 설정하여 모든 요소가 올바르게 메모리에 정렬되도록합니다. 전형적인 64 비트 플랫폼 예 :

struct A { 
    char c; // sizeof(char) == 1; alignof(char) == 1 
    int* ptr; // sizeof(char) == 8; alignof(char) == 8 
} 

포인터는 8 바이트 (64 비트)의 크기, 또한 8 바이트의 정렬 요건을 갖는다. 이 구조체에는 cptr 사이에 7 바이트의 패딩이 있습니다 (예 : offsetof(A, c) == 0offsetof(A, ptr) == 8). 그리고 alignof(A) == 8. A a 인스턴스가 생성 될 때마다 (스택 또는 힙에) &a % 8 == 0&(a.ptr) % 8 == 0이 생성됩니다. (실시 예 SIMD 벡터 지침) 일부 CPU 명령어는 피연산자가 단어 경계에 정렬 될 것을 요구하기 때문에


는 메모리 (8) (또는 4 비트 (32))의, 즉 배수가 이루어진다. 적절한 정렬이 없으면이 지침을 직접 사용할 수없고 프로그램이 느려집니다.
이 예에서는 VkSurfaceKHR

pQueueFamilyIndices

alignof == 8와 포인터.

+0

빈 공간을 사용할 수 있습니다. – Tibrogargan