Qt应用软件【数据篇】大小端数据转换

文章目录

  • 大小端数据介绍
  • 大小端数据在内存中的样子
  • C++大小端数据转换
  • QtAPI大小端转换

大小端数据介绍

大端(Big Endian)和小端(Little Endian)是一种描述计算机存储多字节数据的方式。

想象一下,你有一串数字,例如1234,这个数字需要用两个字节(或更多)来存储。那么问题是,这个数字的哪个部分先存储在内存的起始位置(低地址),哪个部分先存储在内存的结束位置(高地址)

  • 大端:在大端字节序中,像1234这样的数字的高位数字(例如12)会存储在内存的低地址处,而低位数字(例如34)会存储在内存的高地址处。这就好比你在阅读数字时,先读高位再读低位,就像阅读英文文字一样,从左到右。
  • 小端:在小端字节序中,相同的数字1234的低位数字(例如34)会存储在内存的低地址处,而高位数字(例如12)会存储在内存的高地址处。这就好比你在阅读数字时,先读低位再读高位,就像阅读阿拉伯数字一样,从右到左。

不同的计算机架构使用不同的字节序,没有统一的标准。通常,x86架构(包括大多数个人电脑和服务器)使用小端字节序,而一些其他架构如PowerPC和SPARC使用大端字节序。因此,当你在处理二进制数据或者与其他系统进行数据交互时,需要注意字节序的差异,以确保数据被正确解释和处理。这也是为什么在网络通信中会有网络字节序(通常是大端)和主机字节序(取决于计算机架构)之间的转换

大小端数据在内存中的样子

大端(Big Endian)和小端(Little Endian)是两种不同的内存存储格式,它们定义了多字节数据(如整数、浮点数等)在内存中的排列方式。理解这两种格式对于编程和系统设计非常重要,特别是在涉及到网络通信和跨平台数据交换时。

大端模式(Big Endian)

在大端模式下,数据的"大端"(即最高有效字节)存储在内存的低地址端,而数据的"小端"(即最低有效字节)存储在内存的高地址端。这意味着,比如一个32位的整数0x12345678,在内存中的存储顺序(从低地址到高地址)将是:

0x12 0x34 0x56 0x78

小端模式(Little Endian)

相反,在小端模式下,数据的"小端"(即最低有效字节)存储在内存的低地址端,而数据的"大端"(即最高有效字节)存储在内存的高地址端。同样的32位整数0x12345678,在内存中的存储顺序将是:

0x78 0x56 0x34 0x12
Little Endian Memory Layout
Big Endian Memory Layout
0x00: 0x78
0x01: 0x56
0x02: 0x34
0x03: 0x12
0x00: 0x12
0x01: 0x34
0x02: 0x56
0x03: 0x78

在这个图表中,我们展示了一个32位整数(0x12345678)在大端和小端模式下的内存布局。每个方框代表一个字节的内存位置,箭头表示地址的增加方向。从图表中可以清晰地看出,大端模式将最高有效字节放在最低的内存地址处,而小端模式则相反,将最低有效字节放在最低的内存地址处。

通过这样的图表,可以直观地理解大端和小端模式的不同,以及它们在内存中是如何存储数据的。

C++大小端数据转换

  • memcpy大小端转换
// 大端转小端
uint16_t bigEndianValue = 0x1234;
uint16_t littleEndianValue;
memcpy(&littleEndianValue, &bigEndianValue, sizeof(uint16_t));// 小端转大端
uint16_t littleEndianValue = 0x3412;
uint16_t bigEndianValue;
memcpy(&bigEndianValue, &littleEndianValue, sizeof(uint16_t));
  • 宏函数大小端转换
uint16_t bigEndianValue = 0x1234;
uint16_t littleEndianValue = BIG_ENDIAN_TO_LITTLE_ENDIAN_16(bigEndianValue);uint32_t anotherBigEndianValue = 0x12345678;
uint32_t anotherLittleEndianValue = BIG_ENDIAN_TO_LITTLE_ENDIAN_32(anotherBigEndianValue);
  • boost库
#include <boost/endian/conversion.hpp>uint16_t bigEndianValue = 0x1234;
uint16_t littleEndianValue = boost::endian::endian_reverse(bigEndianValue);
  • C++20判断大小端
#include <iostream>
#include <cstdint>int main() {if (std::endian::native == std::endian::big) {std::cout << "This system uses big endian." << std::endl;} else if (std::endian::native == std::endian::little) {std::cout << "This system uses little endian." << std::endl;} else {std::cout << "Unknown endian." << std::endl;}return 0;
}
  • 结构体的大小端转换
#include <iostream>
#include <cstdint>
#include <cstring>//1字节对齐
#pragma pack(push, 1)
struct MyStruct {uint16_t a;uint32_t b;uint16_t c;
};
#pragma pack(pop)MyStruct bigToLittleEndian(const MyStruct& bigEndianValue) {MyStruct littleEndianValue;std::memcpy(&littleEndianValue, &bigEndianValue, sizeof(MyStruct));return littleEndianValue;
}MyStruct littleToBigEndian(const MyStruct& littleEndianValue) {return bigToLittleEndian(littleEndianValue);
}int main() {MyStruct bigEndianValue = {0x1234, 0x56789ABC, 0x5678};MyStruct littleEndianValue = bigToLittleEndian(bigEndianValue);std::cout << "Big Endian Value: " << std::hex << bigEndianValue.a << " " << bigEndianValue.b << " " << bigEndianValue.c << std::endl;std::cout << "Little Endian Value: " << std::hex << littleEndianValue.a << " " << littleEndianValue.b << " " << littleEndianValue.c << std::endl;return 0;
}

QtAPI大小端转换

  • QByteArray
#include <QByteArray>
#include <QtEndian>// 大端转小端
QByteArray bigToLittleEndian(const QByteArray &bigEndianData) {QByteArray littleEndianData(bigEndianData);for (int i = 0; i < littleEndianData.size(); i++) {littleEndianData[i] = bigEndianData.at(littleEndianData.size() - 1 - i);}return littleEndianData;
}// 小端转大端
QByteArray littleToBigEndian(const QByteArray &littleEndianData) {QByteArray bigEndianData(littleEndianData);for (int i = 0; i < bigEndianData.size(); i++) {bigEndianData[i] = littleEndianData.at(bigEndianData.size() - 1 - i);}return bigEndianData;
}int main() {uint16_t bigEndianValue = 0x1234;QByteArray bigEndianData(reinterpret_cast<const char*>(&bigEndianValue), sizeof(uint16_t));QByteArray littleEndianData = bigToLittleEndian(bigEndianData);QByteArray backToBigEndian = littleToBigEndian(littleEndianData);// 输出结果qDebug() << "Big Endian Data:" << bigEndianData.toHex();qDebug() << "Little Endian Data:" << littleEndianData.toHex();qDebug() << "Back to Big Endian Data:" << backToBigEndian.toHex();return 0;
}
  • QDataStream
QDataStream stream(&byteArray, QIODevice::ReadWrite);
stream.setByteOrder(QDataStream::LittleEndian); // 设置为小端
quint16 value;
stream >> value; // 从小端数据中读取16位无符号整数
  • QByteArray
quint16 bigEndianValue = 0x1234;
QByteArray byteArray = QByteArray(reinterpret_cast<const char*>(&bigEndianValue), sizeof(quint16));
quint16 littleEndianValue = qFromBigEndian<quint16>(byteArray.constData());
  • 判断大小端
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {// 当前系统是小端
} else {// 当前系统是大端
}
  • qFromLittleEndian、qToLittleEndian
quint16 littleEndianValue = 0x1234;
quint16 nativeValue = qFromLittleEndian(littleEndianValue); // 转换为本机字节顺序quint16 nativeValue = 0x1234;
quint16 littleEndianValue = qToLittleEndian(nativeValue); // 转换为小端表示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vulhub中spring的CVE-2022-22947漏洞复现

Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本&#xff08;包含&#xff09;以前存在一处SpEL表达式注入漏洞&#xff0c;当攻击者可以访问Actuator API的情况下&#xff0c;将可以利用该漏洞执行任意命令。 参考链接&#xff1a; https://tanzu.vmware.c…

【用Unity开发一款横板跳跃游戏部分需要学习的技术点指南】

*** 用Unity开发一款横板跳跃游戏部分需要学习的技术点指南 空洞骑士是一款基于横板平台跳跃的传统风格2D动作冒险游戏&#xff0c;庞大的游戏世界交错相通&#xff0c;玩家控制小虫子去探索幽深黑暗的洞穴&#xff0c;成为了一代人茶余饭后的惦念&#xff0c;深受玩家喜爱。 …

类银河恶魔城学习记录1-6 Flip基本设置源代码 P33

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Player.cs using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; us…

JAVA 反射和动态管理(二十-完)

反射和动态管理&#xff08;二十-完&#xff09; 反射 反射允许对字段&#xff08;成员变量&#xff09;&#xff0c;成员方法&#xff0c;构造方法的信息进行编程访问。 反射操作可分为获取和解刨。 获取不是从java文件获取&#xff0c;而是从class字节码文件获取。 作用…

MySQL全表扫描:性能杀手的隐患与优化策略

MySQL全表扫描&#xff1a;性能杀手的隐患与优化策略 MySQL数据库作为常用的关系型数据库管理系统之一&#xff0c;全表扫描问题一直困扰着开发者。本文将深入剖析MySQL全表扫描的原理、其对性能的严重影响&#xff0c;同时提供一系列优化策略&#xff0c;助您高效应对MySQL性能…

【NodeJS】fs 模块 (2)

流式文件写入 & 读取 流式文件写入 / 读取适合操作大文件 流式写入 ① 创建可写流&#xff1a;fs.createWriteStream(path[, options]) path&#xff1a;文件路径options&#xff1a;配置对象 flags&#xff1a;文件系统标志&#xff0c;默认值为 wencoding&#xff1a;…

Android battery saver 简单记录

目录 一. battery saver模式的policy (1) DEFAULT_FULL_POLICY 对应的配置和解释: (2) OFF_POLICY 对应的配置也就说不使用policy (3) 获取省电模式下的policy: 二. 对各个参数代码讲解 (1) adjustBrightnessFactor (2) enableAdjustBrightness (3) advertiseIsEnabled…

ctfshow——文件包含

文章目录 web 78——php伪协议第一种方法——php://input第二种方法——data://text/plain第三种方法——远程包含&#xff08;http://协议&#xff09; web 78——str_replace过滤字符php第一种方法——远程包含&#xff08;http://协议&#xff09;第二种方法——data://&…

070:vue中provide、inject的使用方法(图文示例)

第070个 查看专栏目录: VUE 本文章目录 示例背景示例效果图示例源代码父组件代码子组件代码孙组件代码 基本使用步骤 示例背景 本教程是介绍如何在vue中使用provide和inject。在 Vue 中&#xff0c;provide 和 inject 是用于实现祖先组件向后代组件传递数据的一种方式。 在这个…

oracle 触发器事前触发和事后触发区别

Oracle触发器的事前触发和事后触发主要在触发的时机和触发器内部的操作上有所区别。 触发时机&#xff1a;事前触发器是在触发事件发生之前运行&#xff0c;而事后触发器则在触发事件发生之后运行。 获取的数据&#xff1a;事前触发器通常可以获取到事件发生前和新的字段值。O…

Docker存储空间清理

不知不觉服务器存储空间被Docker掏空了… 查看Docker空间占用情况 使用docker system df命令&#xff0c;可以加 -v 查看详情 清理Docker不需要的内容 使用docker system prune -a命令清理Docker 所有停止的容器所有没有被使用的networks所有没容器的镜像所有build cache …

公共用例库计划--个人版(六)典型Bug页面设计与开发

1、任务概述 本次计划的核心任务是开发一个&#xff0c;个人版的公共用例库&#xff0c;旨在将各系统和各类测试场景下的通用、基础以及关键功能的测试用例进行系统性地归纳整理&#xff0c;并以提高用例的复用率为目标&#xff0c;力求最大限度地减少重复劳动&#xff0c;提升…

图论练习4

内容&#xff1a;染色划分&#xff0c;带权并查集&#xff0c;扩展并查集 Arpa’s overnight party and Mehrdad’s silent entering 题目链接 题目大意 个点围成一圈&#xff0c;分为对&#xff0c;对内两点不同染色同时&#xff0c;相邻3个点之间必须有两个点不同染色问构…

Elasticsearch:入门

1. 介绍Elasticsearch 1.1 什么是Elasticsearch Elasticsearch是一款基于开源的分布式搜索和分析引擎&#xff0c;构建在Apache Lucene之上。它旨在提供一个强大且灵活的工具&#xff0c;使用户能够以高效、实时的方式存储、检索和分析大量数据。 1.2 Elasticsearch的主要特…

自动化测试报告生成【Allure】

之前尝试使用过testNG自带的测试报告、优化过reportNG的测试报告&#xff0c;对这两个报告都不能满意。后经查找资料&#xff0c;发现有个神器&#xff1a; Allure&#xff08;已经有allure2了&#xff0c;笔者使用的就是allure2&#xff09;&#xff0c;生成的测试报告与上述…

异或加密原理及简单应用(C语言版)

加密原理&#xff1a; 异或加密是一种基于异或运算的简单加密算法。在二进制运算中&#xff0c;异或&#xff08;XOR&#xff09;的规则是&#xff1a; 0 XOR 0 00 XOR 1 11 XOR 0 11 XOR 1 0 这意味着如果两个比特相同&#xff0c;则结果为0&#xff0c;否则结果为1。异…

八. 实战:CUDA-BEVFusion部署分析-学习spconv的优化方案(Implicit GEMM conv)

目录 前言0. 简述1. 什么是Implicit GEMM Conv2. Explicit GEMM Conv3. Implicit GEMM Conv4. Implicit GEMM Conv优化5. spconv和Implicit GEMM Conv总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0…

Python 中的 __doc__ 属性是用来做什么的?Python 中的 logging 模块是用来做什么的?如何配置日志记录?

Python 中的 doc 属性是用来做什么的&#xff1f; doc 是 Python 中用于存储文档字符串&#xff08;docstring&#xff09;的特殊属性。文档字符串是与模块、类、函数或方法相关联的字符串&#xff0c;用于提供对其功能和使用的简要描述。 主要用途&#xff1a; 文档和注释&a…

WiFi 6 和WiFi 6e 的核心要点

目录 WiFi 6 是什么&#xff1f; WiFi 6/6e 的主要feature功能&#xff1a; 80Mhz and 160Mhz channel 1K QAM WiFi6 支持2.4G band OFDMA&#xff1a;Orthogonal frequency division multiple access OFDMA先把频段分为&#xff1a;Resource Units (RUs) Subcarriers …

使用 Visual Studio Code 在远程计算机上调试 PostgreSQL

使用 Visual Studio Code 在远程计算机上调试 PostgreSQL 1. 概述 PostgreSQL 是一个功能强大的开源关系数据库管理系统&#xff0c;适用于各种应用程序。在开发过程中&#xff0c;调试 PostgreSQL 对于识别和解决问题至关重要。在本博客中&#xff0c;我们将手把手教你使用客…