code

엔디안은 언제 요인이됩니까?

codestyles 2020. 11. 8. 10:02
반응형

엔디안은 언제 요인이됩니까?


내가 이해하는 엔디안은 적어도 가장 일반적인 경우에서 멀티 바이트 단어를 구성하는 바이트의 순서가 다를 때입니다. 따라서 16 비트 정수는 0xHHLL또는 로 저장 될 수 있습니다 0xLLHH.

내가 그렇게 잘못 알고 있지 않다고 가정하면, 엔디안이 다를 수도 있고 다를 수도있는 두 컴퓨터간에 정보를 보낼 때 엔디안이 언제 주요 요소가되는지 알고 싶습니다.

  • 수정없이 문자 배열의 형태로 1의 짧은 정수를 전송하면 256으로 수신되고 해석됩니까?

  • 다음 코드를 사용하여 짧은 정수를 분해하고 재구성하면 엔디안이 더 이상 요인이되지 않습니까?

    // Sender:
    for(n=0, n < sizeof(uint16)*8; ++n) {
        stl_bitset[n] = (value >> n) & 1;
    };
    
    // Receiver:
    for(n=0, n < sizeof(uint16)*8; ++n) {
        value |= uint16(stl_bitset[n] & 1) << n;
    };
    
  • 엔디안을 보상하는 표준 방법이 있습니까?

미리 감사드립니다!


매우 추상적으로 말하면 엔디안은 변수를 문자 배열로 재 해석하는 속성입니다.

실제로 이것은 외부 바이트 스트림 (예 : 파일 또는 소켓) read()에서 송수신 할 때 정확하게 중요합니다 write(). 또는 다시 추상적으로 말하면, 데이터 직렬화 할 때 엔디안이 중요 합니다 (기본적으로 직렬화 된 데이터에는 유형 시스템이없고 멍청한 바이트로 구성되기 때문입니다). 그리고 엔디안은 프로그래밍 언어 내에서 중요 하지 않습니다 . 언어는 표현이 아닌 에서만 작동하기 때문 입니다. 하나에서 다른 것으로 이동하는 것은 세부 사항을 파헤쳐 야하는 곳입니다.

재치-쓰기 :

uint32_t n = get_number();

unsigned char bytesLE[4] = { n, n >> 8, n >> 16, n >> 24 };  // little-endian order
unsigned char bytesBE[4] = { n >> 24, n >> 16, n >> 8, n };  // big-endian order

write(bytes..., 4);

여기서 우리는라고 말할 수 있었고 reinterpret_cast<unsigned char *>(&n)그 결과는 시스템의 엔디안에 따라 달라졌을 것입니다.

그리고 읽기 :

unsigned char buf[4] = read_data();

uint32_t n_LE = buf[0] + buf[1] << 8 + buf[2] << 16 + buf[3] << 24; // little-endian
uint32_t n_BE = buf[3] + buf[2] << 8 + buf[1] << 16 + buf[0] << 24; // big-endian

다시 말하지만, 여기서 우리는라고 말할 수 있었고 uint32_t n = *reinterpret_cast<uint32_t*>(buf)그 결과는 기계 엔디안에 따라 달라졌을 것입니다.


보시다시피, 정수 유형을 사용하면 대수 입력 및 출력 연산을 사용하는 경우 데이터 스트림에 대한 자체 시스템의 엔디안을 알 필요가 없습니다. 와 같은 다른 데이터 유형을 사용 double하면 문제가 더 복잡해집니다.


당신이 장치 사이에 데이터를 전송하는 경우 기록을 위해, 당신은 거의 항상 함께 네트워크 바이트 순서를 사용한다 ntohl, htonl, ntohs, htons. 시스템 및 대상 시스템이 사용하는 것과 관계없이 Endianness에 대한 네트워크 바이트 순서 표준으로 변환됩니다. 물론 두 시스템 모두 이와 같이 프로그래밍되지만 일반적으로 네트워킹 시나리오에 있습니다.


  1. 아니요, 올바른 일반적인 아이디어를 가지고 있습니다. 누락 된 것은 일반적으로 직렬 연결이더라도 네트워크 연결 (최소한 대부분의 네트워크 연결)이 옥텟 (바이트) 수준에서 올바른 엔디안을 보장한다는 사실입니다. 즉, 값이있는 바이트를 보내는 경우 리틀 엔디안 머신에서 0x12의 값이있는 경우에도 빅 엔디안 머신에서 0x12로 수신됩니다.

    짧게 보면 16 진수로 숫자를 보면 아마 도움이 될 것입니다. 0x0001로 시작합니다. 두 바이트로 나눕니다 : 0x00 0x01. 수신하면 0x0100으로 읽히고 256으로 판명됩니다.

  2. 네트워크는 옥텟 수준에서 엔디안을 처리하므로 일반적으로 바이트 내 비트가 아닌 바이트 순서 만 보정하면됩니다.

  3. 아마도 가장 간단한 방법은 전송할 때 htons / htonl을 사용하고 수신 할 때 ntohs / ntohl을 사용하는 것입니다. 충분하지 않은 경우 XDR, ASN.1, CORBA IIOP, Google 프로토콜 버퍼 등과 같은 많은 대안이 있습니다.


보상의 "표준 방식"은 "네트워크 바이트 순서"의 개념이 거의 항상 (AFAIK) 빅 엔디안으로 정의되어 있다는 것입니다.

발신자와 수신자는 모두 유선 프로토콜을 알고 있으며 필요한 경우 전송 전과 수신 후에 변환하여 애플리케이션에 올바른 데이터를 제공합니다. 그러나이 변환 은 애플리케이션이 아닌 네트워킹 계층 내부에서 발생 합니다.


두 엔디안 모두 내가 아는 장점이 있습니다.

  1. Big-endian은 위치 숫자 체계와 유사하기 때문에 개념적으로 이해하기가 더 쉽습니다.
  2. Little-endian은 여러 메모리 크기에 대해 메모리 참조를 재사용 할 때 편리합니다. 간단히 말해, little-endian에 대한 포인터가 unsigned int*있지만 거기에 저장된 값이 <256 인 것을 알고 있다면 포인터를 unsigned char*.

엔디안은 항상 문제입니다. 어떤 사람들은 네트워크에 연결된 모든 호스트가 동일한 OS를 실행한다는 것을 안다면 문제가 없다고 말할 것입니다. 그렇지 않을 때까지 사실입니다. 온라인 데이터의 정확한 형식을 자세히 설명하는 사양을 항상 게시해야합니다. 원하는 형식이 될 수 있지만 모든 엔드 포인트는 형식을 이해하고 올바르게 해석 할 수 있어야합니다.

일반적으로 프로토콜은 숫자 값에 대해 big-endian을 사용하지만 모든 사람이 IEEE 754와 호환되지 않는 경우 제한이 있습니다. 오버 헤드를 감수 할 수 있다면 XDR (또는 선호하는 솔루션)을 사용하고 안전합니다.


Here are some guidelines for C/C++ endian-neutral code. Obviously these are written as "rules to avoid"... so if code has these "features" it could be prone to endian-related bugs !! (this is from my article on Endianness published in Dr Dobbs)

  1. Avoid using unions which combine different multi-byte datatypes. (the layout of the unions may have different endian-related orders)

  2. Avoid accessing byte arrays outside of the byte datatype. (the order of the byte array has an endian-related order)

  3. Avoid using bit-fields and byte-masks (since the layout of the storage is dependent upon endianness, the masking of the bytes and selection of the bit fields is endian sensitive)

  4. Avoid casting pointers from multi-byte type to other byte types.
    (when a pointer is cast from one type to another, the endianness of the source (ie. The original target) is lost and subsequent processing may be incorrect)


You shouldn't have to worry, unless you're at the border of the system. Normally, if you're talking in terms of the stl, you already passed that border.

It's the task of the serialization protocol to indicate/determine how a series of bytes can be transformed into the type you're sending, beit a built-in type or a custom type.

If you're talking built-in only, you may suffice with the machine-abstraction provided by tools provided by your environment]

참고URL : https://stackoverflow.com/questions/7179907/when-does-endianness-become-a-factor

반응형