Program Club

C ++에서 64 비트 정수에 대한 "표준"htonl과 유사한 함수가 있습니까?

proclub 2020. 12. 5. 10:50
반응형

C ++에서 64 비트 정수에 대한 "표준"htonl과 유사한 함수가 있습니까?


어떤 시점에서 64 비트 정수 값을 사용하는 memcache 프로토콜의 구현을 작업 중입니다. 이러한 값은 "네트워크 바이트 순서"로 저장되어야합니다.

uint64_t htonll(uint64_t value)변경을 할 수있는 기능 이 있었으면하는데 안타깝게도 존재한다면 찾을 수 없었습니다.

그래서 1 ~ 2 개의 질문이 있습니다.

  • 이를 수행하는 휴대용 (Windows, Linux, AIX) 표준 기능이 있습니까?
  • 그러한 기능이 없다면 어떻게 구현 하시겠습니까?

기본 구현을 염두에두고 있지만 코드를 이식 가능하게 만들기 위해 컴파일 타임에 엔디안을 확인하는 방법을 모르겠습니다. 그래서 당신의 도움은 여기에서 환영받는 것 이상입니다.)

감사합니다.


다음은 Brian의 솔루션 덕분에 제가 작성한 최종 솔루션입니다.

uint64_t htonll(uint64_t value)
{
    // The answer is 42
    static const int num = 42;

    // Check the endianness
    if (*reinterpret_cast<const char*>(&num) == num)
    {
        const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
        const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL));

        return (static_cast<uint64_t>(low_part) << 32) | high_part;
    } else
    {
        return value;
    }
}

당신은 아마도 bswap_64거의 모든 곳에서 지원된다고 생각하지만 표준이라고 부르지 않을 것입니다.

값이 1 인 int를 만들고 int의 주소를 a로 캐스팅 char*하고 첫 번째 바이트의 값을 확인하여 엔디안을 쉽게 확인할 수 있습니다 .

예를 들면 :

int num = 42;
if(*(char *)&num == 42)
{
   //Little Endian
}
else
{
   //Big Endian
} 

이를 알면 스와핑을 수행하는 간단한 기능을 만들 수도 있습니다.


이식 가능한 크로스 플랫폼 인 엔디안 매크로를 포함하는 부스트를 항상 사용할 수도 있습니다.


#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))

테스트 (1 == htonl (1))는 하드웨어 아키텍처에 바이트 스와핑이 필요한지 여부를 간단히 판단합니다 (슬프게도 런타임에). 컴파일 타임에 아키텍처가 무엇인지 결정하는 이식 가능한 방법이 없기 때문에 우리는 "htonl"을 사용합니다. 바이트 스와핑이 필요한 경우 htonl을 사용하여 한 번에 32 비트를 스왑합니다 (두 개의 32 비트 단어도 스왑하는 것을 기억).


AIX, BSD, Linux 및 Solaris를 포함한 대부분의 컴파일러 및 운영 체제에서 이식 가능한 스왑을 수행하는 또 다른 방법이 있습니다.

#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif

중요한 부분은 __BIG_ENDIAN__또는 사용하는 것입니다 __LITTLE_ENDIAN__. 하지 __BYTE_ORDER__, __ORDER_BIG_ENDIAN____ORDER_LITTLE_ENDIAN__. 일부 컴파일러와 운영 체제는 부족 __BYTE_ORDER__하고 친구입니다.


uint64_t htobe64(uint64_t host_64bits)& uint64_t be64toh(uint64_t big_endian_64bits)시도 할 수 있습니다 .


This seems to work in C; did I do anything wrong?

uint64_t htonll(uint64_t value) {
    int num = 42;
    if (*(char *)&num == 42) {
        uint32_t high_part = htonl((uint32_t)(value >> 32));
        uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL));
        return (((uint64_t)low_part) << 32) | high_part;
    } else {
        return value;
    }
}

To reduce the overhead of the "if num == ..." Use the pre-processor defines:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else
#endif

EDIT: combining the two (used Brian's code):

uint64_t htonll(uint64_t value)
{
     int num = 42;
     if(*(char *)&num == 42)
          return (htonl(value & 0xFFFFFFFF) << 32LL) | htonl(value >> 32);
     else 
          return value;
}

Warning: untested code! Please test before using.

참고URL : https://stackoverflow.com/questions/3022552/is-there-any-standard-htonl-like-function-for-64-bits-integers-in-c

반응형