1、Endian Order
  什么是大小端字节序(Endian Order)?以四字节十六进制整型数0x12345678为例,按照书写习惯,从左到右,高位在前,低位在后,我们称0x12为最高有效字节,0x78为最低有效字节,在存储这个数字时,需要四字节的地址空间,比如说从0x00到0x03,地址空间是从低地址0x00到高地址0x03的一段连续地址,那么,低地址存储最高有效字节的形式为大端(Big Endian),反之,高地址存储最高有效字节的形式为小端(Little Endian),也就是说,大端字节序时,地址0x00存储数字0x12,0x01存储0x34,0x02存储0x56,0x03存储0x78,反之,小端字节序时,地址0x00存储数字0x78,0x01存储0x56,0x02存储0x34,0x03存储0x12,在实际使用中,大端字节序符合我们的书写习惯。另外,对于一个字节来说,其中的八个比特位也有类似的大小端比特序,常见的最高有效位MSB(Most Significant Bit)和最低有效位LSB(Least Significant Bit)就是从这里来的。由于数据传输是逐字节的,最小单位为字节,所以我们需要关心的是大小端字节序,网络字节序为大端字节序,大小端比特序可以忽略。

2、qbswap
  对于给定的处理器来说,其大小端字节序是已知的,Qt在头文件qendian.h提供了若干对大小端进行处理的接口。首先是字节逆序函数qbswap_helper,因为在头文件中定义,所以必须指定为inline,以及模板函数qbswap,其中的转换结果dest不要求字节对齐,实现方式如下:

 1 inline void qbswap_helper(const void *src, void *dest, int size)  2 {  3     for (int i = 0; i < size ; ++i)  4         static_cast<uchar *>(dest)[i] = static_cast<const uchar *>(src)[size - 1 - i];  5 }  6 
 7 template <typename T> inline void qbswap(const T src, void *dest)  8 {  9     qbswap_helper(&src, dest, sizeof(T)); 10 }

3、考虑字节对齐

  考虑到类型安全和字节对齐安全,提供了qToUnalignedqFromUnaligned两个函数,以及六个模板特化函数qbswap,如下:

 1 template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)  2 {  3     const size_t size = sizeof(T);  4 #if QT_HAS_BUILTIN(__builtin_memcpy)
 5  __builtin_memcpy  6 #else
 7  memcpy  8 #endif
 9             (dest, &src, size); 10 } 11 
12 template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src) 13 { 14  T dest; 15     const size_t size = sizeof(T); 16 #if QT_HAS_BUILTIN(__builtin_memcpy)
17  __builtin_memcpy 18 #else
19  memcpy 20 #endif
21             (&dest, src, size); 22     return dest; 23 } 24 
25 #if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32)
26 template <> inline void qbswap<quint64>(quint64 source, void *dest) 27 { 28     qToUnaligned<quint64>(__builtin_bswap64(source), dest); 29 } 30 template <> inline void qbswap<quint32>(quint32 source, void *dest) 31 { 32     qToUnaligned<quint32>(__builtin_bswap32(source), dest); 33 } 34 #else
35 #endif // GCC & Clang intrinsics
36 
37 #if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16)
38 template <> inline void qbswap<quint16>(quint16 source, void *dest) 39 { 40     qToUnaligned<quint16>(__builtin_bswap16(source), dest); 41 } 42 #else
43 #endif // GCC & Clang intrinsics
44 
45 // signed specializations
46 template <> inline void qbswap<qint64>(qint64 source, void *dest) 47 { 48     qbswap<quint64>(quint64(source), dest); 49 } 50 
51 template <> inline void qbswap<qint32>(qint32 source, void *dest) 52 { 53     qbswap<quint32>(quint32(source), dest); 54 } 55 
56 template <> inline void qbswap<qint16>(qint16 source, void *dest) 57 { 58     qbswap<quint16>(quint16(source), dest); 59 }

4、不考虑字节对齐

  如果不考虑字节对齐问题,使用另一个版本的重载函数qbswap更方便,同样有六个特化模板,如下:

 1 template <typename T> T qbswap(T source);  2 
 3 #if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32)
 4 template <> inline quint64 qbswap<quint64>(quint64 source)  5 {  6     return __builtin_bswap64(source);  7 }  8 template <> inline quint32 qbswap<quint32>(quint32 source)  9 { 10     return __builtin_bswap32(source); 11 } 12 #else
13 template <> inline quint64 qbswap<quint64>(quint64 source) 14 { 15     return 0
16         | ((source & Q_UINT64_C(0x00000000000000ff)) << 56) 17         | ((source & Q_UINT64_C(0x000000000000ff00)) << 40) 18         | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24) 19         | ((source & Q_UINT64_C(0x00000000ff000000)) << 8) 20         | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8) 21         | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24) 22         | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40) 23         | ((source & Q_UINT64_C(0xff00000000000000)) >> 56); 24 } 25 
26 template <> inline quint32 qbswap<quint32>(quint32 source) 27 { 28     return 0
29         | ((source & 0x000000ff) << 24) 30         | ((source & 0x0000ff00) << 8) 31         | ((source & 0x00ff0000) >> 8) 32         | ((source & 0xff000000) >> 24); 33 } 34 #endif // GCC & Clang intrinsics
35 
36 #if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16)
37 template <> inline quint16 qbswap<quint16>(quint16 source) 38 { 39     return __builtin_bswap16(source); 40 } 41 #else
42 template <> inline quint16 qbswap<quint16>(quint16 source) 43 { 44     return quint16( 0
45                     | ((source & 0x00ff) << 8) 46                     | ((source & 0xff00) >> 8) ); 47 } 48 #endif // GCC & Clang intrinsics
49 
50 
51 // signed specializations
52 template <> inline qint64 qbswap<qint64>(qint64 source) 53 { 54     return qbswap<quint64>(quint64(source)); 55 } 56 
57 template <> inline qint32 qbswap<qint32>(qint32 source) 58 { 59     return qbswap<quint32>(quint32(source)); 60 } 61 
62 template <> inline qint16 qbswap<qint16>(qint16 source) 63 { 64     return qbswap<quint16>(quint16(source)); 65 } 66 }

5、8 Bits

  对于8个二进制位的类型来说,是不需要考虑大小端的,如下:

1 template <> inline quint8 qbswap<quint8>(quint8 source) 2 { 3     return source; 4 } 5 
6 template <> inline qint8 qbswap<qint8>(qint8 source) 7 { 8     return source; 9 }

6、大小端转换

  大小端转换涉及如下六个函数:

 1 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
 2 
 3 template <typename T> inline T qToBigEndian(T source)  4 { return source; }  5 template <typename T> inline T qFromBigEndian(T source)  6 { return source; }  7 template <typename T> inline T qToLittleEndian(T source)  8 { return qbswap<T>(source); }  9 template <typename T> inline T qFromLittleEndian(T source) 10 { return qbswap<T>(source); } 11 template <typename T> inline void qToBigEndian(T src, void *dest) 12 { qToUnaligned<T>(src, dest); } 13 template <typename T> inline void qToLittleEndian(T src, void *dest) 14 { qbswap<T>(src, dest); } 15 #else // Q_LITTLE_ENDIAN
16 
17 template <typename T> inline T qToBigEndian(T source) 18 { return qbswap<T>(source); } 19 template <typename T> inline T qFromBigEndian(T source) 20 { return qbswap<T>(source); } 21 template <typename T> inline T qToLittleEndian(T source) 22 { return source; } 23 template <typename T> inline T qFromLittleEndian(T source) 24 { return source; } 25 template <typename T> inline void qToBigEndian(T src, void *dest) 26 { qbswap<T>(src, dest); } 27 template <typename T> inline void qToLittleEndian(T src, void *dest) 28 { qToUnaligned<T>(src, dest); } 29 
30 #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN

  如果不考虑字节对齐,还有下面几个特化模板。

 1 template <typename T> inline T qFromLittleEndian(const void *src)  2 {  3     return qFromLittleEndian(qFromUnaligned<T>(src));  4 }  5 
 6 template <> inline quint8 qFromLittleEndian<quint8>(const void *src)  7 { return static_cast<const quint8 *>(src)[0]; }  8 template <> inline qint8 qFromLittleEndian<qint8>(const void *src)  9 { return static_cast<const qint8 *>(src)[0]; } 10 
11 template <class T> inline T qFromBigEndian(const void *src) 12 { 13     return qFromBigEndian(qFromUnaligned<T>(src)); 14 } 15 
16 template <> inline quint8 qFromBigEndian<quint8>(const void *src) 17 { return static_cast<const quint8 *>(src)[0]; } 18 template <> inline qint8 qFromBigEndian<qint8>(const void *src) 19 { return static_cast<const qint8 *>(src)[0]; }