【QT】Qt对大小端字节序的处理
来源:互联网 发布:js 禁用input select 编辑:程序博客网 时间:2024/05/01 23:08
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不要求字节对齐,实现方式如下:
inline void qbswap_helper(const void *src, void *dest, int size){ for (int i = 0; i < size ; ++i) static_cast<uchar *>(dest)[i] = static_cast<const uchar *>(src)[size - 1 - i];}template <typename T> inline void qbswap(const T src, void *dest){ qbswap_helper(&src, dest, sizeof(T));}
3、考虑字节对齐
考虑到类型安全和字节对齐安全,提供了qToUnaligned
和qFromUnaligned
两个函数,以及六个模板特化函数qbswap
,如下:
template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest){ const size_t size = sizeof(T);#if QT_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy#else memcpy#endif (dest, &src, size);}template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src){ T dest; const size_t size = sizeof(T);#if QT_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy#else memcpy#endif (&dest, src, size); return dest;}#if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32)template <> inline void qbswap<quint64>(quint64 source, void *dest){ qToUnaligned<quint64>(__builtin_bswap64(source), dest);}template <> inline void qbswap<quint32>(quint32 source, void *dest){ qToUnaligned<quint32>(__builtin_bswap32(source), dest);}#else#endif // GCC & Clang intrinsics#if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16)template <> inline void qbswap<quint16>(quint16 source, void *dest){ qToUnaligned<quint16>(__builtin_bswap16(source), dest);}#else#endif // GCC & Clang intrinsics// signed specializationstemplate <> inline void qbswap<qint64>(qint64 source, void *dest){ qbswap<quint64>(quint64(source), dest);}template <> inline void qbswap<qint32>(qint32 source, void *dest){ qbswap<quint32>(quint32(source), dest);}template <> inline void qbswap<qint16>(qint16 source, void *dest){ qbswap<quint16>(quint16(source), dest);}
4、不考虑字节对齐
如果不考虑字节对齐问题,使用另一个版本的重载函数qbswap更方便,同样有六个特化模板,如下:
template <typename T> T qbswap(T source);#if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32)template <> inline quint64 qbswap<quint64>(quint64 source){ return __builtin_bswap64(source);}template <> inline quint32 qbswap<quint32>(quint32 source){ return __builtin_bswap32(source);}#elsetemplate <> inline quint64 qbswap<quint64>(quint64 source){ return 0 | ((source & Q_UINT64_C(0x00000000000000ff)) << 56) | ((source & Q_UINT64_C(0x000000000000ff00)) << 40) | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24) | ((source & Q_UINT64_C(0x00000000ff000000)) << 8) | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8) | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24) | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40) | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);}template <> inline quint32 qbswap<quint32>(quint32 source){ return 0 | ((source & 0x000000ff) << 24) | ((source & 0x0000ff00) << 8) | ((source & 0x00ff0000) >> 8) | ((source & 0xff000000) >> 24);}#endif // GCC & Clang intrinsics#if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16)template <> inline quint16 qbswap<quint16>(quint16 source){ return __builtin_bswap16(source);}#elsetemplate <> inline quint16 qbswap<quint16>(quint16 source){ return quint16( 0 | ((source & 0x00ff) << 8) | ((source & 0xff00) >> 8) );}#endif // GCC & Clang intrinsics// signed specializationstemplate <> inline qint64 qbswap<qint64>(qint64 source){ return qbswap<quint64>(quint64(source));}template <> inline qint32 qbswap<qint32>(qint32 source){ return qbswap<quint32>(quint32(source));}template <> inline qint16 qbswap<qint16>(qint16 source){ return qbswap<quint16>(quint16(source));}}
5、8 Bits
对于8个二进制位的类型来说,是不需要考虑大小端的,如下:
template <> inline quint8 qbswap<quint8>(quint8 source){ return source;}template <> inline qint8 qbswap<qint8>(qint8 source){ return source;}
6、大小端转换
大小端转换涉及如下六个函数:
#if Q_BYTE_ORDER == Q_BIG_ENDIANtemplate <typename T> inline T qToBigEndian(T source){ return source; }template <typename T> inline T qFromBigEndian(T source){ return source; }template <typename T> inline T qToLittleEndian(T source){ return qbswap<T>(source); }template <typename T> inline T qFromLittleEndian(T source){ return qbswap<T>(source); }template <typename T> inline void qToBigEndian(T src, void *dest){ qToUnaligned<T>(src, dest); }template <typename T> inline void qToLittleEndian(T src, void *dest){ qbswap<T>(src, dest); }#else // Q_LITTLE_ENDIANtemplate <typename T> inline T qToBigEndian(T source){ return qbswap<T>(source); }template <typename T> inline T qFromBigEndian(T source){ return qbswap<T>(source); }template <typename T> inline T qToLittleEndian(T source){ return source; }template <typename T> inline T qFromLittleEndian(T source){ return source; }template <typename T> inline void qToBigEndian(T src, void *dest){ qbswap<T>(src, dest); }template <typename T> inline void qToLittleEndian(T src, void *dest){ qToUnaligned<T>(src, dest); }#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
如果不考虑字节对齐,还有下面几个特化模板。
template <typename T> inline T qFromLittleEndian(const void *src){ return qFromLittleEndian(qFromUnaligned<T>(src));}template <> inline quint8 qFromLittleEndian<quint8>(const void *src){ return static_cast<const quint8 *>(src)[0]; }template <> inline qint8 qFromLittleEndian<qint8>(const void *src){ return static_cast<const qint8 *>(src)[0]; }template <class T> inline T qFromBigEndian(const void *src){ return qFromBigEndian(qFromUnaligned<T>(src));}template <> inline quint8 qFromBigEndian<quint8>(const void *src){ return static_cast<const quint8 *>(src)[0]; }template <> inline qint8 qFromBigEndian<qint8>(const void *src){ return static_cast<const qint8 *>(src)[0]; }
- 【QT】Qt对大小端字节序的处理
- QT转换字节大小为最接近的大小单位
- QT 图像大小处理
- Qt 与C11 对string 的处理
- QT中对XML的处理
- QT中对BSON的处理
- QT中对2维的处理
- Qt 获取屏幕的大小
- Qt对字符的处理(beta1.0)
- Qt不同版本对中文字符的处理
- 对指针占用字节大小的理解
- 字节序-大小端
- 字节序-大小端
- 字节序-大小端
- 大小端字节序
- 字节序大小端
- 大小端字节序
- 大小端字节序
- html 布局
- Gradle篇一——groovy基础
- html 表单
- Android系统从加电到Home桌面出现流程分析(基于Android-2.3)
- html 框架
- 【QT】Qt对大小端字节序的处理
- HDU 6078 dp
- css基础笔记总结
- 重构代码学习笔记一:重构的原则
- UVA 1331 【区间DP+三角剖分】
- 20170809 JAVA 方法的重写
- 汇编基础
- leetCode
- WEB-INF文件下建了目录无法跳转的原因