首页 > 其他分享 >Qt 大小端字节序的处理

Qt 大小端字节序的处理

时间:2024-03-13 09:24:05浏览次数:23  
标签:Qt dest void source template 大小 inline qbswap 字节

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]; }

 

标签:Qt,dest,void,source,template,大小,inline,qbswap,字节
From: https://www.cnblogs.com/ybqjymy/p/18069841

相关文章

  • Qt 大端模式、小端模式及其转换
    大端模式和小端模式是计算机中经常涉及到的两种字节序,也有大端对齐、小端对齐、大尾、小尾等叫法。一、起源说起这两种模式,就不得不提一下大端(Big-endian)和小端(Little-endian)这两个英文上的起源。“endian”一词来源于乔纳森·斯威夫特的小说格列佛游记。Lilli......
  • Qt QTextStream 类(文本流)和 QDataStream 类(数据流)
    一、二者区别(1)QTextStream类:用于对数据进行文本格式的读/写操作,可在QString、QIODevice或QByteArray上运行,比如把数据输出到QString、QIODevice或QByteArray对象上,或进行相反的操作。(2)QDataStream类:用于对数据进行二进制格式的读/写操作,QDataStream只可在QIOD......
  • 错误:在 /tmp/easy_install-rad8_t5b/PyQt5-5.14.0.tar.gz #15 中找不到安装脚本
    thePyQt55.14.0isbrokenbecausecan'tnotinstallonresppi3.youcantoinstallaversionofPyQt5thatworkingfineonresp.followthesteps:PyQt55.14.0已损坏,因为无法无法安装在resppi3上。您可以安装一个在resp上运行良好的PyQt5版本,请按照以下......
  • QT生成固定长度的随机字符串
    最近项目中有一个需要使用QT生成固定长度随机字符串的需求,需求也很简单,就是生成一个n位的仅包含0-9以及大写字母的字符串,因为这也是第一次使用QT自身的随机数,这里就做一下简单记录。废话不多说,直接上代码。1QStringgetRandomString(intlength)2{3qsrand(QDateTi......
  • 基于QT实现的微量气体数据记录软件
      最近收到一个要求实现力高泰的微量气体分析仪数据下载与记录软件的需求。需要支持力高泰LI-7810、LI-78150、LI-7820、LI-850/830等微量气体分析仪,另外还包括配套的阀箱、冷阱及采样单元的数据获取与记录。其中LI-7810、LI-78150、LI-7820采用以太网通讯,应用成蓄意为MQTT;LI-85......
  • Qt QByteArray与int、float、vector互转
    QByteArray的转换一般在串口通信中常用,将int、float、double转换为4个字节的数组(如255->[0,0,0,255],本文章一律用10进制表示),或将4个字节的数组转换为int、float、double(如[0,0,0,255]->255)。在QT界面中的使用流程,笔者总结为以下思路:从上位机发送一帧指令到串口(封包、根据具体......
  • Qt QTextEdit添加文字的方式
    1.append 添加方式,在文本内容后面添加新的文本内容2.insertText添加方式,可以在textEdit的任何方式添加文本效果和代码1#include"widget.h"2#include"ui_widget.h"3#include<QPalette>4#include<QBrush>5#include<QFont>6#include<QTextCursor&......
  • 最新宽字节注入攻击和代码分析技术
    宽字节注入攻击宽字节注入攻击的测试地址在本书第2章。访问id=1',页面的返回结果如图4-51所示,程序并没有报错,反而多了一个转义符(反斜杠)。   图4-51  从返回的结果可以看出,参数id=1在数据库查询时是被单引号包围的。当传入id=1'时,传入的单引号又被转义符(反斜杠)转义,导......
  • C++ Qt开发:QNetworkAccessManager网络接口组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QNetworkAccessManager组件实现Web网页访问。QNetworkAccessManager是Qt网络模块中的关......
  • Qt--编译安装QWT
    1.下载https://sourceforge.net/projects/qwt/files/2.编译   编译参考如下:1QtCreator打开源码内的qwt.pro,注意:编译器选择Release版本,编译器使用与creator的一样的版本,这里使用msvc201532bit。2打开编译开关,在qwt->otherfiles->qwt.prf中,去掉QMAKE_RPATHDI......