2013-10-25 3 views
5

빅 엔디 언 머신에서 보낸 데이터를 리틀 엔디안 시스템에있는 디코더로 디코딩하려고합니다. 나는이 일을별로하지 않았고 혼란 스럽다고 느낀다.엔디안 변환 C++

비트 세트를 사용하여 데이터를 인쇄하므로 특정 32 비트 구조에서 어떻게 나오는지 정확하게 볼 수 있으며 필요한 데이터가 비트 시퀀스 중간에 있음을 알 수 있습니다.

자, 32 비트 값을 가지고 있으면 큰 것으로부터 작은 것으로 이동하려면 바이트 순서를 뒤집을 수 있습니다. 내가 그렇게한다면, 내 수는 내가 예상 한 곳에서 끝나지 않을 것이다 (손으로).

예를 들어, 32 비트 부호없는 int 있습니다. 내 Big-Endian 컴퓨터에서 0x50000000으로오고 있다는 것을 알고 있습니다. 리틀 엔디 언 머신에서 bitset을 사용하여 이것을 프린트 할 때 cout << "packSpare 32: " << bitset<32>(Data.pack_Spare).to_string() << endl; 나는 0x00005000을 얻는다. 따라서 첫 번째 두 바이트를 순서대로 두 번째 두 바이트와 순서대로 바꾼 것처럼 보입니다.

나는 원래 이런 구조체했다 :

#pragma pack(push, 1) 
    struct PACK_SPARE 
    { 
     int   Spare3:28; 
     int   Heading_Reference:1; 
     int   Spare2:1; 
     int   H_Valid:1; 
     int   Spare5:1; 
    }; 
    #pragma pack(pop) 

가 큰 엔디안 시스템에서 전송되는 순서의 역순이지만, 그래서, 비트가 일어나고있는 몇 가지 명백한 교환에 관한 issure을 발견 전 32 비트로 모든 것을 가져온 다음 스왑 한 다음 데이터를 인쇄하고 싶었습니다. 지금 막 사용 중입니다 int pack_Spare;

전체 32 비트 값을 스왑하는 대신 두 개의 16 비트 청크를 사용하고 스왑하는 것입니까? 미안 내가 말했듯이 이것이 이해가되지 않는다면 나는 혼란 스럽다.

편집 이 데이터는 네트워크를 통해 들어오는되지 않습니다. 비디오 파일에서 비트를 스트리밍하고 있습니다. 이 데이터를 해당 값에 저장합니다. 그래서 내 질문에 만약 비트셋을 사용한다면 왜 32 비트 int를 가지고 있고 그런 다음 fread 데이터를 그 변수에 넣었을 것인가? 왜 바이트 단위로하는 것보다 내 32 비트 int의 2 개의 16 비트 그룹을 바꿔 놓을까요? 나는 0x50000000을 기대하고 있지만 0x00005000 (0000과 5000은 모든 바이트의 순서를 뒤집어 놓고있는 전형적인 엔디안 스와핑을 기대하고있는 대신 스왑 된 상태가된다.)을 얻는다.

+0

"hton()"또는 "ntoh()"에서 "network"라는 단어는 바이트가 어디서 왔는지 가리키는 것이 아니라 빅 엔디안 인 "network byte order"를 참조합니다. – Fozi

+0

맞아,하지만 내 문제가 빅 엔디안에서 변환되지 않았다, 그것은 (바이트 순서를 스와핑하여 한 형식에서 다른 형식으로 변환) 예상했던 일을 대신, 한 번에 16 비트를 스와핑 (비트 17- 32 명은 1-16 명, 1-16 명은 17-32 명). 왜 그렇게하는지 확신 할 수 없었습니다. – shawleigh17

+0

귀하의 문제는 프로토콜 수준에 있다고 생각합니다. – Fozi

답변

2

나는 종종 소개를 넘어 아무것도 위키 백과을 권장하지 않지만, 내가 찾았어요 좋은 여기 endian discussion (귀하의 질문에 대한 대답에 왜 내 (32)의 두 개의 16 비트 그룹을 교환한다 비트 정수로하지 않고 바이트 단위로 수행 하시겠습니까?).

토론의 2/3이 링크의 페이지 아래로 발생합니다 ...이을 찾습니다

enter image description here

은 같은 페이지에 엔디안에 관한 몇 가지 흥미로운 일이 있습니다.

+0

근본적으로, 원자 원소는 내가 예상했던 것 대신에 16 비트입니다. 이것은 8 비트였습니다. 나는 powerpc에서 윈도우 7 64 비트로 갈 예정이다. – shawleigh17

+1

그 논의에서 그렇습니다. 원자 요소는 해당 구현에 대해 _ 16 비트로 정의됩니다. 나는 PowerPC의 구현에 익숙하지 않지만 당신이보고있는 현상은 그와 같은 것을 암시한다. – ryyker

5

그냥 hton()과 공동으로 사용하십시오. 네트워크와 네이티브 머신의 바이트 순서를 변환 해, 시프트 및 마스킹 등의 실제의 비트 연산을 적용합니다. 즉각적인 메모리 액세스로 주변을 뒤적 거리지 않아도됩니다.

4

전송할 때 네트워크 바이트 순서 (htonX() 사용)로 변환 한 다음 다시 읽을 때 (ntohX() 사용) 다시 변환해야합니다.

참고 : 제공된 링크는 Windows 버전의 기능을위한 것입니다. POSIX 시스템에도 비슷한 서명이 있습니다.

0

일을 재 배열하는 데 사용 된 한 가지 방법은 결합을 사용하는 것입니다. 나는 Endianings 새로운 해요,하지만 곧 나는 내가 가지고 올 수있는 가장 빠른 방법 (저는 믿습니다, 집중적 인 이하 CPU)는 folowing 코드를 사용하여, 그래서 필요한 것을 알아 냈 : 내 경우

template <class T, const int size = sizeof (T)> 
class cTypeConvert final 
{ 
    public: 
     union 
     { 
      T val; 
      char c [size]; 
     }uTC; 
}; 

char s 문자열을 사용하면 size에서 0까지 cTypeConvert::uTC.c[] 배열을 공급하고이 템플릿을 인스턴스화 한 유형으로 읽어야합니다. 가장 중요한 부분은 필자가 필요로하는 모든 표준 유형에 사용할 수 있으며 항상 작동한다는 것입니다.

이 템플릿을 사용하기 전에 유형을 char로 변환해야한다면 위의 설명보다 약간 더 많은 CPU를 낭비해야합니다.