티스토리 뷰

일하면서

[short code] 8 byte endian 변환

신랑각시 2017. 12. 26. 15:35

안녕하세요.


신랑 각시의 신랑입니다.


오늘은 일 하면서, 간만에 Endian 변환이 필요한 경우가 생겼습니다.


Endian 이란, 컴퓨터에서 기본 타입 ( primitive time ) 을 다룰 때 byte 순서를 말합니다.


예를 들어, 4 byte integer 형을 다룰 때 Big endian 을 사용하는 컴퓨터는 바이트 순서를 좌측부터 계산합니다. (좌측이 큰 값이 됩니다.)


1을 표현하면, 0x00000001 으로 표현됩니다.


Little endian 을 사용하는 컴퓨터는 바이트 순서를 우측부터 계산합니다. (우측이 큰 값이 됩니다.) 


1을 표현하면, 0x01000000 으로 표현됩니다.


 예전에 다루던 시스템 (HP_UX) 같은 경우에 Big endian 이여서 char 배열에 int 형을 그대로 memcpy 하는 경우도 많았습니다만, 요즘은 Little endian 을 사용하는 x86 아키텍처를 많이 다루다 보니까, 이전 같은 변환은 안됩니다.


네트워크를 통하여 데이터를 전송하는 경우에는 양쪽의 송/수신 시스템이 Little endian 을 사용하더라도 Big endian 으로 변환하여 전달하는 경우가 일반적입니다.


어차피 프로토콜이라는게 시스템간의 약속이니까, 프로토콜을 정할 때, Little endian 을 사용한다고 명시하면 변환 이슈가 없을 수도 있겠습니다만, 아직 네트워크에서는 Big endian 으로 데이터를 다루는 것 같습니다.


2 byte ( short ) 나 4 byte ( int ) 경우에는 htons(), htonl() 이나 ntohs(), ntohl() 을 사용할 수 있으나 8 byte ( 64 bit 에서는 long 같은.. ) 는 아직까지는 직접 만들어 사용하고 있습니다.



void ToBigEndian(long & _t) {
	if(1 == htonl(1))
		return ;
		
	_t = htonl(_t >> 32) | ((uint64_t)htonl(_t) << 32);
}


void FromBigEndian(long & _t) {
	if(1 == ntohl(1))
		return ;
		
	_t = ntohl(_t >> 32) | ((uint64_t)ntohl(_t) << 32);
}


설명 하자면, 


if(1 == htonl(1))

    return ;


이것은 Endian 확인을 위함 입니다. c++20 에는 std::endian 이 제공되는 것 같지만 그 전까지는 변환이 필요한지 체크해 봐야겠습니다.


_t = htonl(_t >> 32) | ((uint64_t)htonl(_t) << 32); 에서 우측에 보면 htonl(_t) 로 처리 합니다. htonl 은 4 byte 변환을 함으로 굳이 bit shift 를 하지 않았습니다.


byte 순서를 바꾸는 것임으로 이렇게 할 수 도 있겠습니다.



void ToBigEndian(long & _t) {
	if(1 == htonl(1))
		return ;
		
    std::string s((const char *)&_t, sizeof(_t));
    std::reverse(s.begin(), s.end());    
    memcpy((char *)&_t, s.data(), s.length());
}


위와 같이 하려면, #include <algorithm> 과 #include <cstring> 을 추가해야 겠지요..


이상 endian 변환이였습니다.

댓글