2010-04-25 2 views
2

임 내에서 비트 쉽게 acccess 온라인 자습서와 나는 다음과 같은 구조를 가지고 :C++ 노조 데이터 구조의 DirectX 세트를 통해 실행하는 DWORD

struct CUSTOMVERTEX 
{ 
FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag 
DWORD color;  // from the D3DFVF_DIFFUSE flag 
} 

의 DirectX 내 기본적인 이해가 가지 그쪽으로 색상 날 리드를 8 비트 알파, 레드, 그린 및 블루 채널로 구성됩니다.

이 채널에 동쪽으로 액세스하려고합니다. 보다는합니다 (CUSTOMVERTEX 구조 내에서) 다음 코드를 여러 번 쓰기 :

public: int red() 
{ 
    return (color & 0x00FF0000) >> 16; 
} 

나는 노동 조합의 조합, 예를 들어 구조 더 우아한 somution를 작성할 수

struct CUSTOMVERTEX 
{ 
    FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag 

    #pragma pack(2) 
    union 
    { 
     DWORD color;  // from the D3DFVF_DIFFUSE flag 

     struct 
     { 
      char a; 
      char r; 
      char g; 
      char b; 
     }; 
    }; 
} 

그러나이 예상대로 작동 나타나지 않고, R, g의 값은 & B 거의 예컨대 색상 뭐죠의 역을 표시 색상이 0x12345678 인 경우 a = 0x78, r = 0x56 이것은 endieness 문제입니까?

또한이 솔루션에서 기대할 수있는 다른 문제는 무엇입니까? 예 : 색상 멤버에서 오버플로?

내가 묻는 것은 무엇인지 ... 나는 이것을 할 수있는 더 좋은 방법이 있습니까?!

+1

한 가지는 것은 그 안에 필드 구조체는 여분의 바이트로 패딩되어 각각이 2/4/... (플랫폼 특정)의 주소 배수를 갖도록 할 수 있습니다. 즉, 구조체의 실제 메모리 레이아웃에는 모든 필드의 일부가 아닌 바이트가 포함될 수 있습니다. 따라서 구조체의 크기가 sizeof (DWORD)와 같지 않을 수도 있습니다. –

답변

2

예, 이것은 엔디안 문제입니다. 하나의 플랫폼 만 지원하는 경우 아키텍처의 엔디안에 따라 구조체 멤버를 배치 할 수 있습니다. 다중 아키텍쳐를 다루는 경우 엔디 언 (endian)에 의존하는 다중 struct 멤버 레이아웃을 #define 정의해야합니다.

구조체와 공용체는 항상 나에게 우아 해 보이지만 비트 연산은이 중 더 이식성이 있습니다. 이런 식으로 할 때, 구조체가 불확실한 불행이 일어나기 전에 내가 기대하는 크기인지 확인하기 위해 시작 코드에 어설 션을 사용합니다.

C++에서는 데이터를 캡슐화하고 작업을 수행하는 클래스를 작성할 수 있습니다.

1

DWORD 색상이 0x12345678 인 경우 주소가 & 인 바이트가 리틀 엔디 언 시스템에서 0x78입니다.

기술적으로 노동 조합의 트릭은 정의되지 않은 동작으로 이어집니다. 접근 자 메서드의 문제점은 무엇입니까?

+0

말할 것도없이 * 아무것도 * 잘못되었습니다 ... 나는 각 채널에 대해 별도의 getter 및 setter 함수를 작성하지 않고 도망 갈 수 있는지 궁금합니다. 나는 멀리 갈 수있는 가장 우아한 해결책을 찾고있다. C++과 DirectX에 대해 다소 새로운 Im은 ID가 튜토리얼을 사용하기보다는 코드를 약간 수정하려고 시도했다고 생각했습니다. 나는 가능한 가장 우아한 해결책을 얻으려고 노력하고 있으며, 노동 조합이 그것을 제공 할 것이라고 생각했습니다. –

+0

나는 본다. endianess 문제는 필드를 재배치하여 해결하기 쉽습니다. 참으로 조합에 더 깨끗해 보입니다. 그리고 당신은 약간의 불쾌한 행동으로 놀랄 것 같지 않지만 이론적으로는 가능합니다. –

+1

이 특수한 조합 트릭은 실제로 잘 정의되어 있습니다. 그러나 char 배열에 memcpy가 가지고있는 것과 같은 방법으로 DWORD의 문자를 기계 순서로 읽는 것으로 정의됩니다. – Joshua

1

이 작업을 수행하려면 올바른 endianess 문제가 있는지 확인하고 패딩 문제가 올바른지 확인해야합니다 (비표준 #pragma 문이 필요함). 비록 당신이 이식성에 관심이 없다하더라도 (DirectX는 Windows에만 해당됨), 당신은 여전히이 목적을 위해 인라인 함수를 사용하는 것이 좋습니다. 매우 비슷한 몇 가지 스크립트가 필요할 수도 있지만, 그 중 몇 가지 기능이 복잡해지면 여전히 union보다 작다고 주장 할 수 있습니다. 컴파일러를 변경하면 컴파일러가 변경 될 가능성이 적어지고 (특히 침묵하는 경우) 컴파일 할 가능성이 적어지고 코드를 읽는 다음 사람이 자신이 원하는 작업을 수행하고 있다고 확신 할 수 있습니다.

#pragma pack(1) 대신 #pragma pack(2)을 사용한 이유는 무엇입니까?

는 그리고 당신이 그렇게 다른 재료가 예기치 않게 작동하지 않는 원래 팩 설정을 '& 복원 저장'을하는 것을 잊지 마세요 #pragma pack를 사용하는 경우 : 고려해야 할

#pragma pack(push) 
#pragma pack(2) 
//... 
#pragma pack(pop) 
+0

포장 옵션 재설정에 대한 좋은 지적은 ... 당신이해야한다는 것을 몰랐습니다! #pragma pack (2) 문제는 msdn에 대한 예에서 남겨 뒀고 번호를 변경하는 것을 잊었습니다. 나는 이미 마스크와 비트 교대의 혼란을 사용하는 작업 솔루션을 가지고 있지만, 경험상 이것이 새로운 개발자를 혼란스럽게 할 수 있다는 것을 안다. (시작했을 때 나 자신도 포함되어있다!) 나는 유니온과 함께 C# properties와 비슷한 것을 목표로 삼고 있었다. 나는 드로잉 보드에 그때를 추측한다! –

+0

#pragma pack을 사용하는 이유는 무엇입니까? – Goz

관련 문제