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

前端 未结 30 2542
难免孤独
难免孤独 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:18

    Portable technique for implementing optimizer-friendly unaligned non-inplace endian accessors. They work on every compiler, every boundary alignment and every byte ordering. These unaligned routines are supplemented, or mooted, depending on native endian and alignment. Partial listing but you get the idea. BO* are constant values based on native byte ordering.

    uint32_t sw_get_uint32_1234(pu32)
    uint32_1234 *pu32;
    {
      union {
        uint32_1234 u32_1234;
        uint32_t u32;
      } bou32;
      bou32.u32_1234[0] = (*pu32)[BO32_0];
      bou32.u32_1234[1] = (*pu32)[BO32_1];
      bou32.u32_1234[2] = (*pu32)[BO32_2];
      bou32.u32_1234[3] = (*pu32)[BO32_3];
      return(bou32.u32);
    }
    
    void sw_set_uint32_1234(pu32, u32)
    uint32_1234 *pu32;
    uint32_t u32;
    {
      union {
        uint32_1234 u32_1234;
        uint32_t u32;
      } bou32;
      bou32.u32 = u32;
      (*pu32)[BO32_0] = bou32.u32_1234[0];
      (*pu32)[BO32_1] = bou32.u32_1234[1];
      (*pu32)[BO32_2] = bou32.u32_1234[2];
      (*pu32)[BO32_3] = bou32.u32_1234[3];
    }
    
    #if HAS_SW_INT64
    int64 sw_get_int64_12345678(pi64)
    int64_12345678 *pi64;
    {
      union {
        int64_12345678 i64_12345678;
        int64 i64;
      } boi64;
      boi64.i64_12345678[0] = (*pi64)[BO64_0];
      boi64.i64_12345678[1] = (*pi64)[BO64_1];
      boi64.i64_12345678[2] = (*pi64)[BO64_2];
      boi64.i64_12345678[3] = (*pi64)[BO64_3];
      boi64.i64_12345678[4] = (*pi64)[BO64_4];
      boi64.i64_12345678[5] = (*pi64)[BO64_5];
      boi64.i64_12345678[6] = (*pi64)[BO64_6];
      boi64.i64_12345678[7] = (*pi64)[BO64_7];
      return(boi64.i64);
    }
    #endif
    
    int32_t sw_get_int32_3412(pi32)
    int32_3412 *pi32;
    {
      union {
        int32_3412 i32_3412;
        int32_t i32;
      } boi32;
      boi32.i32_3412[2] = (*pi32)[BO32_0];
      boi32.i32_3412[3] = (*pi32)[BO32_1];
      boi32.i32_3412[0] = (*pi32)[BO32_2];
      boi32.i32_3412[1] = (*pi32)[BO32_3];
      return(boi32.i32);
    }
    
    void sw_set_int32_3412(pi32, i32)
    int32_3412 *pi32;
    int32_t i32;
    {
      union {
        int32_3412 i32_3412;
        int32_t i32;
      } boi32;
      boi32.i32 = i32;
      (*pi32)[BO32_0] = boi32.i32_3412[2];
      (*pi32)[BO32_1] = boi32.i32_3412[3];
      (*pi32)[BO32_2] = boi32.i32_3412[0];
      (*pi32)[BO32_3] = boi32.i32_3412[1];
    }
    
    uint32_t sw_get_uint32_3412(pu32)
    uint32_3412 *pu32;
    {
      union {
        uint32_3412 u32_3412;
        uint32_t u32;
      } bou32;
      bou32.u32_3412[2] = (*pu32)[BO32_0];
      bou32.u32_3412[3] = (*pu32)[BO32_1];
      bou32.u32_3412[0] = (*pu32)[BO32_2];
      bou32.u32_3412[1] = (*pu32)[BO32_3];
      return(bou32.u32);
    }
    
    void sw_set_uint32_3412(pu32, u32)
    uint32_3412 *pu32;
    uint32_t u32;
    {
      union {
        uint32_3412 u32_3412;
        uint32_t u32;
      } bou32;
      bou32.u32 = u32;
      (*pu32)[BO32_0] = bou32.u32_3412[2];
      (*pu32)[BO32_1] = bou32.u32_3412[3];
      (*pu32)[BO32_2] = bou32.u32_3412[0];
      (*pu32)[BO32_3] = bou32.u32_3412[1];
    }
    
    float sw_get_float_1234(pf)
    float_1234 *pf;
    {
      union {
        float_1234 f_1234;
        float f;
      } bof;
      bof.f_1234[0] = (*pf)[BO32_0];
      bof.f_1234[1] = (*pf)[BO32_1];
      bof.f_1234[2] = (*pf)[BO32_2];
      bof.f_1234[3] = (*pf)[BO32_3];
      return(bof.f);
    }
    
    void sw_set_float_1234(pf, f)
    float_1234 *pf;
    float f;
    {
      union {
        float_1234 f_1234;
        float f;
      } bof;
      bof.f = (float)f;
      (*pf)[BO32_0] = bof.f_1234[0];
      (*pf)[BO32_1] = bof.f_1234[1];
      (*pf)[BO32_2] = bof.f_1234[2];
      (*pf)[BO32_3] = bof.f_1234[3];
    }
    
    double sw_get_double_12345678(pd)
    double_12345678 *pd;
    {
      union {
        double_12345678 d_12345678;
        double d;
      } bod;
      bod.d_12345678[0] = (*pd)[BO64_0];
      bod.d_12345678[1] = (*pd)[BO64_1];
      bod.d_12345678[2] = (*pd)[BO64_2];
      bod.d_12345678[3] = (*pd)[BO64_3];
      bod.d_12345678[4] = (*pd)[BO64_4];
      bod.d_12345678[5] = (*pd)[BO64_5];
      bod.d_12345678[6] = (*pd)[BO64_6];
      bod.d_12345678[7] = (*pd)[BO64_7];
      return(bod.d);
    }
    
    void sw_set_double_12345678(pd, d)
    double_12345678 *pd;
    double d;
    {
      union {
        double_12345678 d_12345678;
        double d;
      } bod;
      bod.d = d;
      (*pd)[BO64_0] = bod.d_12345678[0];
      (*pd)[BO64_1] = bod.d_12345678[1];
      (*pd)[BO64_2] = bod.d_12345678[2];
      (*pd)[BO64_3] = bod.d_12345678[3];
      (*pd)[BO64_4] = bod.d_12345678[4];
      (*pd)[BO64_5] = bod.d_12345678[5];
      (*pd)[BO64_6] = bod.d_12345678[6];
      (*pd)[BO64_7] = bod.d_12345678[7];
    }
    

    These typedefs have the benefit of raising compiler errors if not used with accessors, thus mitigating forgotten accessor bugs.

    typedef char int8_1[1], uint8_1[1];
    
    typedef char int16_12[2], uint16_12[2]; /* little endian */
    typedef char int16_21[2], uint16_21[2]; /* big endian */
    
    typedef char int24_321[3], uint24_321[3]; /* Alpha Micro, PDP-11 */
    
    typedef char int32_1234[4], uint32_1234[4]; /* little endian */
    typedef char int32_3412[4], uint32_3412[4]; /* Alpha Micro, PDP-11 */
    typedef char int32_4321[4], uint32_4321[4]; /* big endian */
    
    typedef char int64_12345678[8], uint64_12345678[8]; /* little endian */
    typedef char int64_34128756[8], uint64_34128756[8]; /* Alpha Micro, PDP-11 */
    typedef char int64_87654321[8], uint64_87654321[8]; /* big endian */
    
    typedef char float_1234[4]; /* little endian */
    typedef char float_3412[4]; /* Alpha Micro, PDP-11 */
    typedef char float_4321[4]; /* big endian */
    
    typedef char double_12345678[8]; /* little endian */
    typedef char double_78563412[8]; /* Alpha Micro? */
    typedef char double_87654321[8]; /* big endian */
    

提交回复
热议问题