当前位置: 首页 > news >正文

可以做日语翻译的兼职网站深圳搜索优化排名

可以做日语翻译的兼职网站,深圳搜索优化排名,百度做网站不给FTP密码,平面设计培训网站后面打算写Qt关于网络编程的博客,网络编程就绕不开字节流数据传输,字节流数据的传输一般是根据协议来定义对应的报文该如何组包,那这就必然牵扯到了大端字节序和小端字节序的问题了。不清楚的大小端的可以看一下相关资料:大小端模…

后面打算写Qt关于网络编程的博客,网络编程就绕不开字节流数据传输,字节流数据的传输一般是根据协议来定义对应的报文该如何组包,那这就必然牵扯到了大端字节序和小端字节序的问题了。不清楚的大小端的可以看一下相关资料:大小端模式_百度百科 (baidu.com)。

这里看一个具体的例子比如某个报文协议是这样定的:

报头...
设备编号U16(两个字节)
设备温度U16(两个字节)
设备湿度U16(两个字节)
设备状态U16(两个字节)
报尾...

那么传输过程的报文结构,除去头尾之外应该是这样的:

代码报文结构体这样定义

struct DeviceData {quint16 number;quint16 temperature;quint16 humidness;quint16 status;
};

然后简单测试一下

  QByteArray data;DeviceData d;d.number = 0x1234;d.temperature = 0x5678;d.humidness = 0x4321;d.status = 0x8756;data.append(reinterpret_cast<char *>(&d), sizeof(DeviceData));qDebug() << data.toHex();

编译运行查看一下打印结果:

如果看了前面关于大小端的资料应该就会明白为什么这里打印结果是“3412785621435687”,这里也有一个参考的文章:大小端格式由编译器,操作系统还是CPU决定的?答案是CPU_大端cpu采用小端编译链-CSDN博客我的机器cpu,如果不采取任何处理,这里输出的确实是小端数据,如果是大端那么就会输出对应的“1234567843218756”。如果上文中举例的协议定的就是小端数据传输那么就是这样写,无需做任何处理。如果是大端数据传输则需要做对应的处理。同样上文中还存在一个问题,比如设备编号协议里面定的是无符号一个字节即uint8类型的。那么结构体将会这样定义:

struct DeviceData {quint8 number;quint16 temperature;quint16 humidness;quint16 status;
};

测试代码:

  QByteArray data;DeviceData d;d.number = 0x12;d.temperature = 0x5678;d.humidness = 0x4321;d.status = 0x8756;data.append(reinterpret_cast<char *>(&d), sizeof(DeviceData));qDebug() << data.toHex();

这里将结构体转QByteArray使用了reinterpret_cast,可以自己查一下static_castdymatic_castreinterpret_cast以及Qt的qobject_cast有什么区别。同样还可以使用QByteArray的setRawData方法:

QByteArray data;
data.setRawData(reinterpret_cast<char *>(&d), sizeof(DeviceData));

结果也是一样的。

将对应QByteArray转回结构体直接使用memcpy即可。例如上面的例子:

DeviceData dd;

memcpy(&dd, data.constData(), sizeof(DeviceData));

打印输出:

为什么打印是这样,可以先看看这个结构体的大小,打印 sizeof(DeviceData)可以看到是8个字节,结构体成员一个quint8,三个quint16,大小:1+2+2+2为什么是8而不是7, 这个就需要了解关于字节对齐的知识了:字节对齐_百度百科 (baidu.com)

直接采用1字节对齐:

#pragma pack(push, 1);
struct DeviceData {quint8 number;quint16 temperature;quint16 humidness;quint16 status;
};
#pragma pack(pop);

再查看打印:

然后sizeof(DeviceData)也是7了(这里使用1字节对齐会影响效率)。·

回到关于大小端的问题,代码里面采用的是结构体转QByteArray,这样就牵扯到了依靠系统自己的大小端来处理了,代码不灵活。可以写一个通用的方法来根据需求转换对应需要的字节序。

方法一:

思路是一个字节一个字节进行拷贝使用QByteArray的append方法以及位移操作。

比如一个无符号四字节的quint32 u32=0x12345678(大端就是12345678,小端就是78563412),先执行下列代码:

  quint32 u32 = 0x12345678;QByteArray data;data.append(u32);qDebug() << data.toHex();

查看打印:

也就是说QByteArray的 append方法在这种情况下并不会将整数 u32 转换为字节流,而是将整数的低字节(最低有效字节)追加到 QByteArray中。

转化为小端数据:

原生数据操作原生数据QByteArray进行append追加
12345678右移0位1234567878
12345678右移8位001234567856
00123456右移16位00001234785634
00001234右移24位0000001278563412

转化为大端数据:

原生数据操作原生数据QByteArray进行append追加
12345678右移24位0000001212
12345678右移16位000012341234
00123456右移8位00123456123456
00001234右移0位1234567812345678

对应代码:

  quint32 u32 = 0x12345678;//输出小端数据QByteArray littleEndian;littleEndian.append(u32);littleEndian.append(u32 >> 8);littleEndian.append(u32 >> 16);littleEndian.append(u32 >> 24);qDebug() << "little:" << littleEndian.toHex();//输出大端数据QByteArray bigEndian;bigEndian.append(u32 >> 24);bigEndian.append(u32 >> 16);bigEndian.append(u32 >> 8);bigEndian.append(u32);qDebug() << "bigEndian:" << bigEndian.toHex();

编译运行查看打印:

 对应转回同理,下面是完整代码:

  quint32 u32 = 0x12345678;//输出小端数据QByteArray littleEndian;littleEndian.append(u32);littleEndian.append(u32 >> 8);littleEndian.append(u32 >> 16);littleEndian.append(u32 >> 24);qDebug() << "littleEndian:" << littleEndian.toHex();quint32 u32x = 0;u32x |= static_cast<quint8>(littleEndian[0]);u32x |= (static_cast<quint8>(littleEndian[1]) << 8);u32x |= (static_cast<quint8>(littleEndian[2]) << 16);u32x |= (static_cast<quint8>(littleEndian[3]) << 24);qDebug() << "ori data:" << u32x;//输出大端数据QByteArray bigEndian;bigEndian.append(u32 >> 24);bigEndian.append(u32 >> 16);bigEndian.append(u32 >> 8);bigEndian.append(u32);qDebug() << "bigEndian:" << bigEndian.toHex();quint32 u32y = 0;u32y |= (static_cast<quint8>(bigEndian[0]) << 24);u32y |= (static_cast<quint8>(bigEndian[1]) << 16);u32y |= (static_cast<quint8>(bigEndian[2]) << 8);u32y |= static_cast<quint8>(bigEndian[3]);qDebug() << "ori data:" << u32y;

编译运行查看打印:

305419896对应的16进制就是0x12345678:

其他数据类型同理,这里写成模板函数:

template <typename T>
static QByteArray toData(const T &value, bool isLittle) {QByteArray data;for (int i = 0; i < sizeof(T); ++i) {int bitOffset = (isLittle) ? i : sizeof(T) - i - 1;data.append(value >> bitOffset * 8);}return data;
}template <typename T>
static void fromData(const QByteArray &data, bool isLittle, T &value) {for (int i = 0; i < sizeof(T); ++i) {int bitOffset = (isLittle) ? i : sizeof(T) - i - 1;value |= (static_cast<quint8>(data[i]) << bitOffset * 8);}
}

上面例子代码改为:

  quint32 u32 = 0x12345678;//输出小端数据QByteArray littleEndian = toData(u32, true);qDebug() << "littleEndian:" << littleEndian.toHex();quint32 u32x = 0;fromData(littleEndian, true, u32x);qDebug() << "ori data:" << u32x;//输出大端数据QByteArray bigEndian = toData(u32, false);qDebug() << "bigEndian:" << bigEndian.toHex();quint32 u32y = 0;fromData(bigEndian, false, u32y);qDebug() << "ori data:" << u32y;

编译运行查看打印:

跟前面的一致。

方法二:

思路是使用QDataStream的读写数据,然后借助QDataStream的setByteOrder方法,具体就不多细讲,直接看模板函数:

template <typename T>
QByteArray toData1(T value, bool isLittle) {QByteArray data;QDataStream stream(&data, QIODevice::WriteOnly);if (isLittle)stream.setByteOrder(QDataStream::LittleEndian);elsestream.setByteOrder(QDataStream::BigEndian);stream << value;return data;
}template <typename T>
void fromData1(const QByteArray &data, bool isLittle, T &value) {QDataStream stream(data);if (isLittle)stream.setByteOrder(QDataStream::LittleEndian);elsestream.setByteOrder(QDataStream::BigEndian);stream >> value;
}

将上面例子改为使用这两个方法:

  quint32 u32 = 0x12345678;//输出小端数据QByteArray littleEndian = toData1(u32, true);qDebug() << "littleEndian:" << littleEndian.toHex();quint32 u32x = 0;fromData1(littleEndian, true, u32x);qDebug() << "ori data:" << u32x;//输出大端数据QByteArray bigEndian = toData1(u32, false);qDebug() << "bigEndian:" << bigEndian.toHex();quint32 u32y = 0;fromData1(bigEndian, false, u32y);qDebug() << "ori data:" << u32y;

编译运行查看打印:

与方法一结果一致。

方法三:

借助Qt的QtEndian:

首先qt有判断当前CPU是大端还是小端的宏:

例如:

#if Q_BYTE_ORDER == Q_BIG_ENDIANqDebug() << "current endian is big";
#endif#if Q_BYTE_ORDER == Q_LITTLE_ENDIANqDebug() << "current endian is little";
#endif

编译运行查看打印:

因为我的是x86是小端。

对应Qt也有一些大小端转换的方法:

具体使用有兴趣的可以探究一下,我没有过多研究Qt的这个。 

http://www.hkea.cn/news/234074/

相关文章:

  • 武汉企业建站系统模板下载官方正版百度
  • 上海做网站国际财经新闻
  • 用废旧盒子做家用物品网站seo排名工具
  • 企业铭做网站域名解析在线查询
  • 怎么注册自己的小程序网站优化分析
  • 荆州网站建设流程网站设计培训
  • 网站支付怎么做的seo职业技能培训班
  • 做csgo直播网站上海知名网站制作公司
  • 深圳住建局官方网站seo网站关键词优化快速官网
  • 网站建设需要php吗企业的互联网推广
  • 苏中建设集团官方网站电商软文广告经典案例
  • 网站开发需要什么开发工具代做百度首页排名价格
  • 北京网站设计多少钱微信引流推广
  • 网站建设实施背景分析百度指数里的资讯指数是什么
  • 小程序定制开发深圳公司网站的优化seo
  • 构建一个网站域名查询平台
  • 蚌埠网站关键词优化推广下载
  • 看房地产的app在哪看aso安卓优化
  • 网站与域名的区别扬州整站seo
  • 哪些网站可以进行域名注册公司关键词seo
  • 如何申请一个网站 做视频百度小说搜索热度排行榜
  • 天津做网站选择津坤科技b重庆seo教程搜索引擎优化
  • 什么网站做热能表好百度一下电脑版首页网址
  • 点击图片直接进入网站怎么做如何使用免费b站推广网站
  • 手机网站建设软件怎么在百度上做广告推广
  • 南京做网站团队手机app免费制作平台
  • 17173游戏网搜索优化指的是什么
  • 公司做网站需要给百度交钱吗百度竞价推广方案
  • 网站建设的关键seo推广小分享
  • 写小说的小网站百度关键词排名优化