How do I convert between big-endian and little-endian values in C++?

前端 未结 30 2524
难免孤独
难免孤独 2020-11-21 23:18

How do I convert between big-endian and little-endian values in C++?

EDIT: For clarity, I have to translate binary data (double-precision floating point values and 3

30条回答
  •  北海茫月
    2020-11-22 00:15

    If you take the common pattern for reversing the order of bits in a word, and cull the part that reverses bits within each byte, then you're left with something which only reverses the bytes within a word. For 64-bits:

    x = ((x & 0x00000000ffffffff) << 32) ^ ((x >> 32) & 0x00000000ffffffff);
    x = ((x & 0x0000ffff0000ffff) << 16) ^ ((x >> 16) & 0x0000ffff0000ffff);
    x = ((x & 0x00ff00ff00ff00ff) <<  8) ^ ((x >>  8) & 0x00ff00ff00ff00ff);
    

    The compiler should clean out the superfluous bit-masking operations (I left them in to highlight the pattern), but if it doesn't you can rewrite the first line this way:

    x = ( x                       << 32) ^  (x >> 32);
    

    That should normally simplify down to a single rotate instruction on most architectures (ignoring that the whole operation is probably one instruction).

    On a RISC processor the large, complicated constants may cause the compiler difficulties. You can trivially calculate each of the constants from the previous one, though. Like so:

    uint64_t k = 0x00000000ffffffff; /* compiler should know a trick for this */
    x = ((x & k) << 32) ^ ((x >> 32) & k);
    k ^= k << 16;
    x = ((x & k) << 16) ^ ((x >> 16) & k);
    k ^= k << 8;
    x = ((x & k) <<  8) ^ ((x >>  8) & k);
    

    If you like, you can write that as a loop. It won't be efficient, but just for fun:

    int i = sizeof(x) * CHAR_BIT / 2;
    uintmax_t k = (1 << i) - 1;
    while (i >= 8)
    {
        x = ((x & k) << i) ^ ((x >> i) & k);
        i >>= 1;
        k ^= k << i;
    }
    

    And for completeness, here's the simplified 32-bit version of the first form:

    x = ( x               << 16) ^  (x >> 16);
    x = ((x & 0x00ff00ff) <<  8) ^ ((x >>  8) & 0x00ff00ff);
    

提交回复
热议问题