2013-02-04 2 views
1

저는 프로젝트에서 데이터 구조를 사용하고 paricular 구조의 컨텍스트에서 구조체 패딩에 대한 의문점이 있습니다. 먼저 아래에 주어진 구조를보십시오. Visual Studio 2008 컴파일러를 사용합니다.C++의 구조체 패딩에 대해

typedef struct tagDATA_PACK 
{ 
    DWORD dDataLength; 
    BYTE bFlags; 
    BYTE bAttrib; 
    BYTE bOffset; 
}DATA_PACK; 

질문 1 : 위 구조의 크기는 얼마입니까? 8 바이트를 표시합니다. 맞습니다. 그러나,

은 아래에 주어진 수정 된 구조를 고려합니까?

typedef struct tagDATA_PACK 
{ 
    DWORD dDataLength; 
    BYTE bFlags; 
}DATA_PACK; 

여기서의 크기는 상기 8byte 구조와 동일하다. 제 생각에 여기 컴파일러가 여분의 3 바이트를 추가 할 것입니까? BYTE bFlags 이후 또는 그 이전입니까?

귀하의 모든 답변에 크게 감사드립니다.

답변

4

구조체 및 클래스의 정렬 및 패딩은 표준에 의해 지정되지 않습니다. 그것은 전적으로 컴파일러에게 달려 있습니다. 그러나 모든 정상적인 컴파일러는 기본 플랫폼 인 ABI를 따릅니다. 귀하의 경우 플랫폼은 Windows이고 Windows 플랫폼 ABI가 준수됩니다.

이 경우 패딩은 두 구조체 모두 마지막 멤버 뒤에 있습니다. 첫 번째 구조체에는 여분의 패딩 바이트가 하나 있고 두 번째 구조체에는 세 개의 추가 패딩 바이트가 있습니다.

구조체의 최대 입력 크기 4를 가지며, 그 전체 크기가 모두 구조체를 들면 4의 배수 여야한다는 것을 의미, 구조체를 수용 (4)의 작은 복수 8.

각 데이터 인 type에는 정렬 속성이 있습니다. 4 바이트 데이터 유형은 4의 정렬을 갖습니다. 2 바이트 데이터 유형은 2의 정렬을가집니다. 4의 정렬을 갖는 유형은 구조체의 시작에서 4 바이트 오프셋에 배치 될 때 정렬됩니다. 정렬이 2 인 유형은 구조체의 시작에서 2 바이트 오프셋에 놓일 때 정렬됩니다. 등등.

구성원은 구성원의 선언 순서와 구성원의 정렬 특성을 모두 고려하여 가장 작은 오프셋으로 배치됩니다. 구조체 내부 패딩 예를 들어

이 구조체

struct MyStruct 
{ 
    char c; 
    int i; 
}; 
고려

, c의 배향은 1이고, i의 배향 그래서, c는 1 바이트 경계 상에 배치되는 제이며 i은 4 바이트 경계에 있어야합니다. 즉, c은 0 오프셋을 가지며 3 패딩 바이트가 있고 i은 4 오프셋으로 배치됩니다.

+0

는, 여분 패딩 바이트가 추가 장소를 추론 그렇지? – RyanAdamVeet

+0

예, 컴파일러는 구조체를 레이아웃하는 방법을 결정합니다. –

+0

실제로 기본적으로 하나의 합리적인 방법으로 만 수행 할 수있는 표준에 따른 많은 제약이 있습니다. –

1

컴파일러가 원하는 곳. 중요하다면, 어쨌든 휴대용이 아닌 것을하고있는 것입니다. 그렇다면 왜 그렇게 중요합니까? 이 밖에

+0

사실이 구조체와 구조체를 따라 보관할 데이터를위한 BYTE 배열을 만듭니다. 따라서 전체 크기는 구조 자체가 아니라 여분의 데이터 버퍼를 포함합니다. 변수 BYTE bOffset은 데이터 오프셋 주소를 저장합니다. 나는 구조체 구성원 이외의 다른 데이터에 액세스하는 동안 문제가 생길 것입니다. – RyanAdamVeet

0

검사 :

typedef struct myTagDATA_PACK3 
{ 
    char c; 
    double d; 
    int i; 
}DATA_PACK3; 

는 24 바이트를 보여줍니다. 즉 : double : 8 바이트. int : 4 바이트 + (4 바이트 패딩) = 8 바이트. char : 1 바이트 + (7 바이트 패딩) = 8 바이트.


총계 : 24 바이트.

+0

이 질문에 정확히 어떻게 대답합니까? –

+0

ㅎ, 그렇지는 않지만 여전히 멋지다! – thang

+0

@DavidHeffernan, 이것은 실제로 귀하의 답안을 보여줍니다. –

1

은 컴파일러까지이기 때문에 모든 컴파일러에 맞는 답변이 있지만 언어 사양에 따라 레이아웃에 몇 가지 제한이 있습니다. 이러한 제한은 C의 모든 구조, C++ 03의 "일반 오래된 데이터"(기본적으로 C의 기능 만 사용함을 의미) 및 C++ 11의 "표준 레이아웃"구조 (생성자 및 소멸자 허용)에 적용됩니다. 제한 사항은 : 제 1 부재의 형태로 구조

  • (Reinterpret-) 주조 포인터가 제 1 부재 (C++ §9.2 11/20)에 유효한 포인터를 생성한다. 첫 번째 멤버보다 먼저 패딩 할 수 없다는 의미입니다.
  • 유니온의 두 구조가 같은 초기 부분 (동일한 순서의 같은 유형의 멤버)을 갖고 유니온이 그 중 하나를 통해 초기화되면 이들 초기 멤버는 다른 멤버를 통해 액세스 할 수 있습니다 (C++ 11 § 9.2/19). 회원 오프셋은 그 전에 선언 된 회원들에 의해서만 결정될 수 있음을 의미합니다.

표준 레이아웃에 대한 제한이 중요합니다. 기본 클래스 또는 가상 멤버가있는 클래스도 마찬가지입니다.

메모리를 낭비하지 않기를 바란다면 실제로 이것은 모든 컴파일러에서 사용되는 하나의 실용적인 알고리즘 만 남게됩니다. 다양한 원시 타입의 크기와 정렬 요구 사항이 플랫폼마다 다르므로 모든 컴파일러가 동일한 입력에 대해 동일한 레이아웃을 생성한다는 것을 의미하지는 않습니다. 알고리즘은 : 0

  • 오프셋에서
    • 은 정렬을 필요로 나누어 오프셋있어 제 가능한 다음 각 부재를 놓고 제 1 부재를 놓는다.
    • 구조체의 크기를 임의의 구성원 중 가장 큰 정렬의 다음 배수로 반올림합니다.
    • 구조의 정렬 요구 사항은 모든 구성원 중 가장 큰 정렬입니다.

    (내가 MSVC++에 대한 특정 MSDN이 곳을 설명 거의,하지만 신속하게 찾을 수 없습니다) 컴파일러를 의미

  • +0

    +1 좋은 파기 : p – thang

    관련 문제