C++与Android处理16进制大端/小端数据实例(二百七十六)

news2025/3/17 1:21:58

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2.大小端介绍
      • 🐓2.1 大端模式
      • 🐓2.2 小端模式
      • 🐓2.3 作用及应用
      • 🐓2.4结论
    • 🌻3.代码实例
      • 🐓3.1 C++处理大端、小端数据
      • 🐓3.2 Android处理大端、小端数据
      • 🐓3.3 C语言处理大端、小端数据

🌻1.前言

本篇目的:C++与Android处理16进制大端/小端数据实例

🌻2.大小端介绍

  • 大小端模式是指计算机系统中多字节数据的存储方式和传输方式,它主要分为大端模式(Big-Endian)和小端模式(Little-Endian)。

🐓2.1 大端模式

  • 在大端模式中,高字节存储在低地址位置,而低字节存储在高地址位置。换句话说,一个数的最高有效字节(Most Significant Byte, MSB)存放在内存的起始位置。大端模式的特点是数据的书写顺序与其在内存中的存储顺序一致,这样在查看内存时,数据看起来更直观。例如,对于一个32位整数0x12345678,在大端模式下的存储顺序如下:
地址   值
0x00   12
0x01   34
0x02   56
0x03   78

🐓2.2 小端模式

小端模式则是将低字节存储在低地址位置,高字节存储在高地址位置。即最低有效字节(Least Significant Byte, LSB)放在内存的起始位置。与大端模式相反,小端模式的数据存储顺序和书写顺序相反。例如,对于同样的32位整数0x12345678,在小端模式下的存储顺序如下:

地址   值
0x00   78
0x01   56
0x02   34
0x03   12

🐓2.3 作用及应用

  • 大小端模式的选择与计算机的体系结构和应用需求有关。不同的处理器体系结构可能会采用不同的字节存储方式。
  1. 网络通信:在网络通信中,大端模式(也称为网络字节序)被广泛采用。这是因为大端模式在数据传输时,最高有效字节先传输,便于数据在不同系统之间进行一致的传递和解释。互联网协议(如TCP/IP)就使用大端模式,这使得不同设备之间的数据交换更为统一和标准化。

  2. 跨平台数据处理:当程序需要在不同平台上运行时(例如在不同的处理器架构之间传递数据),了解并处理大小端模式是必要的。某些处理器(如x86架构)采用小端模式,而其他处理器(如某些RISC架构)可能采用大端模式。在这种情况下,程序需要正确地转换数据的字节顺序,以确保数据的一致性和正确性。

  3. 文件格式和数据存储:某些文件格式或数据存储协议可能规定了特定的字节序。例如,WAV音频文件和许多图像文件格式规定了使用小端模式存储数据。这种规定确保了文件在不同系统上读取时的一致性。

🐓2.4结论

  • 大小端模式是计算机系统中处理多字节数据的重要概念,理解和正确应用这些模式对于开发跨平台软件、网络协议和处理特定文件格式至关重要。
  • 大端模式以其直观的内存布局适用于网络通信和标准化的数据传输,而小端模式由于其在某些处理器上的效率优势,被广泛应用于多种处理器架构中。在实际应用中,根据具体需求选择合适的字节序模式是确保数据正确处理的关键。

🌻3.代码实例

🐓3.1 C++处理大端、小端数据

#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdint>

// 判断系统是否为小端
bool isLittleEndian() {
    uint16_t number = 0x1;
    return (*(char *)&number == 0x1);
}

// 进行字节序转换(32位)
uint32_t swapEndian32(uint32_t val) {
    return ((val >> 24) & 0x000000FF) |
           ((val >> 8) & 0x0000FF00) |
           ((val << 8) & 0x00FF0000) |
           ((val << 24) & 0xFF000000);
}

// 打印缓冲区内容(小端字节序)
void printBufferLittleEndian(const std::vector<uint8_t>& buffer, const std::string& bufferName) {
    std::string bufferHex;
    for (size_t i = 0; i < buffer.size(); i += 4) {
        uint32_t val = 0;
        // 读取4个字节
        for (size_t j = 0; j < 4 && (i + j) < buffer.size(); ++j) {
            val |= (static_cast<uint32_t>(buffer[i + j]) << (j * 8));
        }
        // 如果系统不是小端字节序,则需要转换字节序
        if (!isLittleEndian()) {
            val = swapEndian32(val);
        }
        // 将4字节的值转换为十六进制字符串
        std::ostringstream hexStream;
        hexStream << std::setfill('0') << std::setw(8) << std::hex << val;
        bufferHex += hexStream.str() + " ";
    }
    std::cout << bufferName << ": " << bufferHex << std::endl;
}

// 打印write_buffer的内容
void printWriteBuffer(const std::vector<uint8_t>& writeBuffer) {
    printBufferLittleEndian(writeBuffer, "Write Buffer");
}

// 打印read_buffer的内容
void printReadBuffer(const std::vector<uint8_t>& readBuffer) {
    printBufferLittleEndian(readBuffer, "Read Buffer");
}

int main() {
    // 初始化示例数据
    std::vector<uint8_t> writeBuffer(256);
    for (int i = 0; i < 256; ++i) {
        writeBuffer[i] = static_cast<uint8_t>(i);
    }

    std::vector<uint8_t> readBuffer(256);
    for (int i = 0; i < 256; ++i) {
        readBuffer[i] = static_cast<uint8_t>(255 - i);
    }

    // 打印缓冲区内容
    printWriteBuffer(writeBuffer);
    printf("\n");
    printReadBuffer(readBuffer);
    return 0;
}

🐓3.2 Android处理大端、小端数据

#include <cutils/log.h>
#include <iomanip>
#include <stdint.h>

// 判断系统是否为小端
bool isLittleEndian() {
  uint16_t number = 0x1;
  return (*(char *)&number == 0x1);
}

// 进行字节序转换(32位)
uint32_t swapEndian32(uint32_t val) {
  return ((val >> 24) & 0x000000FF) |
    ((val >> 8) & 0x0000FF00) |
    ((val << 8) & 0x00FF0000) |
    ((val << 24) & 0xFF000000);
}

// 打印缓冲区内容(小端字节序)
void printBufferLittleEndian(const char* buffer, size_t size, const char* bufferName) {
  std::string bufferHex;
  for (size_t i = 0; i < size; i += 4) {
    uint32_t val = 0;
    // 读取4个字节
    for (size_t j = 0; j < 4 && (i + j) < size; ++j) {
      val |= (static_cast<uint32_t>(static_cast<uint8_t>(buffer[i + j])) << (j * 8));
    }
    // 如果系统不是小端字节序,则需要转换字节序
    if (!isLittleEndian()) {
      val = swapEndian32(val);
    }
    // 将4字节的值转换为十六进制字符串
    char hex[9];
    snprintf(hex, sizeof(hex), "%08x", val);
    bufferHex += hex;
    bufferHex += " ";
  }
  ALOGE("%s: %s", bufferName, bufferHex.c_str());
}

// 打印write_buffer的内容
void printWriteBuffer(const binder_write_read& bwr) {
  const char* writeBuffer = reinterpret_cast<const char*>(bwr.write_buffer);
  printBufferLittleEndian(writeBuffer, bwr.write_size, "Write Buffer");
}

// 打印read_buffer的内容
void printReadBuffer(const binder_write_read& bwr) {
  const char* readBuffer = reinterpret_cast<const char*>(bwr.read_buffer);
  printBufferLittleEndian(readBuffer, bwr.read_size, "Read Buffer");
}

int main() {
  binder_write_read bwr;

  // 初始化示例数据
  bwr.write_size = 256;
  char writeData[256];
  for (int i = 0; i < 256; ++i) {
    writeData[i] = i;
  }
  bwr.write_buffer = reinterpret_cast<binder_uintptr_t>(writeData);

  bwr.read_size = 256;
  char readData[256];
  for (int i = 0; i < 256; ++i) {
    readData[i] = 255 - i;
  }
  bwr.read_buffer = reinterpret_cast<binder_uintptr_t>(readData);

  // 打印缓冲区内容
  printWriteBuffer(bwr);
  printReadBuffer(bwr);
  return 0;
}

🐓3.3 C语言处理大端、小端数据

/***********************************************************
* Author        : 公众号: Android系统攻城狮
* Create time   : 2024-05-21 10:07:14 星期二
* Filename      : little_big_duan_for_C.cpp
* Description   :
************************************************************/

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>

// 判断系统是否为小端
bool isLittleEndian() {
    uint16_t number = 0x1;
    return (*(char *)&number == 0x1);
}

// 进行字节序转换(32位)
uint32_t swapEndian32(uint32_t val) {
    return ((val >> 24) & 0x000000FF) |
           ((val >> 8) & 0x0000FF00) |
           ((val << 8) & 0x00FF0000) |
           ((val << 24) & 0xFF000000);
}

// 打印缓冲区内容(小端字节序)
void printBufferLittleEndian(const char* buffer, size_t size, const char* bufferName) {
    char bufferHex[1024] = {0}; // 假设缓冲区最大为1024字节
    char hex[9];

    for (size_t i = 0; i < size; i += 4) {
        uint32_t val = 0;
        // 读取4个字节
        for (size_t j = 0; j < 4 && (i + j) < size; ++j) {
            val |= (uint32_t)((uint8_t)buffer[i + j]) << (j * 8);
        }
        // 如果系统不是小端字节序,则需要转换字节序
        if (!isLittleEndian()) {
            val = swapEndian32(val);
        }
        // 将4字节的值转换为十六进制字符串
        snprintf(hex, sizeof(hex), "%08x", val);
        strncat(bufferHex, hex, sizeof(bufferHex) - strlen(bufferHex) - 1);
        strncat(bufferHex, " ", sizeof(bufferHex) - strlen(bufferHex) - 1);
    }
    printf("%s: %s\n", bufferName, bufferHex);
}

// 假设binder_write_read_01结构如下
typedef struct {
    void* write_buffer;
    size_t write_size;
    void* read_buffer;
    size_t read_size;
} binder_write_read_01;

// 打印write_buffer的内容
void printWriteBuffer(const binder_write_read_01* bwr) {
    const char* writeBuffer = (const char*)(bwr->write_buffer);
    printBufferLittleEndian(writeBuffer, bwr->write_size, "Write Buffer");
}

// 打印read_buffer的内容
void printReadBuffer(const binder_write_read_01* bwr) {
    const char* readBuffer = (const char*)(bwr->read_buffer);
    printBufferLittleEndian(readBuffer, bwr->read_size, "Read Buffer");
}

int main() {
    // 示例使用
    uint8_t write_data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    uint8_t read_data[] = {0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
    binder_write_read_01 bwr = {write_data, sizeof(write_data), read_data, sizeof(read_data)};

    printWriteBuffer(&bwr);
    //printReadBuffer(&bwr);

    return 0;
}

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

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

相关文章

微服务中使用Maven BOM来管理你的版本依赖

摘要: 原创出处 sf.gg/a/1190000021198564 「飘渺Jam」欢迎转载&#xff0c;保留摘要&#xff0c;谢谢&#xff01; 为什么要使用BOM? 如何定义BOM? 项目使用方法? BOM&#xff08;Bill of Materials&#xff09;是由Maven提供的功能,它通过定义一整套相互兼容的jar包版…

使用docker commit创建新镜像

前言 我们知道&#xff0c;从docker-hub上拉取的镜像所创建的容器是最小版本的&#xff0c;比如ubuntu内部是没有vim编辑器的&#xff0c;我们需要自己手动安装&#xff0c;但是当我们安装后假如有人把我们的容器误删了&#xff0c;那么我们再次根据原始镜像创建的容器就没有了…

Windows安装VMware(Broadcom)

1.安装前提 1.检查BIOS中是否开启了虚拟化技术。1.1 打开任务管理器&#xff0c;查看性能&#xff0c;CPU部分&#xff0c;虚拟化处于“已启用”状态。1.2 如果没有开启&#xff0c;则需要进入BIOS系统&#xff0c;将 Intel Virtualization Technology改为Enalble。2.下载VMwa…

小阿轩yx-PXE 高效批量网络装机

小阿轩yx-PXE 高效批量网络装机 部署PXE远程安装服务 PXE 概述 PXE&#xff08;Preboot eXcution Environment&#xff0c;预启动执行环境&#xff0c;在操作系统之前运行&#xff09;技术的网络装机方法&#xff0c;是由 Intel 公司开发的网络引导技术&#xff0c;工作在 C…

二进制中1的个数c++

题目描述 计算鸭给定一个十进制非负整数 NN&#xff0c;求其对应 22 进制数中 11 的个数。 输入 输入包含一行&#xff0c;包含一个非负整数 NN。(N < 10^9) 输出 输出一行&#xff0c;包含一个整数&#xff0c;表示 NN 的 22 进制表示中 11 的个数。 样例输入 100 …

IS-IS链路状态数据库

原理概述 一个OSPF链路状态数据库是若干条LSA的集合。与此相似&#xff0c;一个IS-IS链路状态数据库是由若干条LSP的集合。与OSPF链路状态数据库不同&#xff0c;IS-IS链路状态数据库有Level-1和Level-2之分。 在IS-IS协议中&#xff0c;每一条LSA都有一条剩余生存时间、一个…

『USB3.0Cypress』FPGA开发(3)GPIF II短包零包时序分析

文章目录 1.时序参数2.FX3_PCLK3.短包和零包3.1短包时序3.2零包ZLP时序 4.传送门 1.时序参数 AN65974文档中明确了操作GPIF II接口时的时序参数&#xff0c;上一篇文章中给出了读写时序图&#xff0c;本篇第二节给出ZLP写周期时序&#xff0c;这里说明相关的时序参数。应该注意…

校园二手书交易|基于SprinBoot+vue的校园二手书交易管理系统(源码+数据库+文档)

校园二手书交易管理系统 目录 基于SprinBootvue的校园二手书交易管理系统 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3 卖家用户功能模块 4 用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八…

WPF之容器标签之Canvas布局标签

Canvas: 定义一个区域&#xff0c;可在其中使用相对于 Canvas 区域的坐标以显式方式来定位子元素。 实例 可以在子标签使用Canvas属性设置定位 <Canvas Width"500" Height"300"><StackPanel Width"100" Height"100"Backgro…

基于51单片机的火灾检测设计(仿真+程序+原理图+论文报告+讲解视频)

基于51单片机的火灾检测设计 基于51单片机的火灾检测设计&#xff08;仿真程序原理图论文报告&#xff09;功能要求仿真图&#xff1a;原理图&#xff1a;源程序&#xff1a;论文/报告&#xff1a;资料清单&#xff1a; 基于51单片机的火灾检测设计&#xff08;仿真程序原理图论…

数据库操作(事务)

描述&#xff1a;事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或者撤销操作请求&#xff0c;这些操作要么同时成功&#xff0c;要么同时失败 一。事务的操作&#xff1a; 开启事务&#xff1a;star…

Linux入门攻坚——23、DNS和BIND基础入门2

前一篇实践了正向解析服务器的配置使用&#xff0c;如何配置反向解析呢&#xff1f; 反向区域&#xff1a; 区域名称&#xff1a;网络地址反写.in-addr.arpa. 192.168.138. --> 138.168.192.in-addr.arpa. (1)定义区域&#xff1a; zone "ZONE_NAME" I…

Unity实现TableView

基于Scrollview封装的TableView&#xff0c;实现对视野外的Cell回收利用&#xff0c;减少创建Cell的开销。 核心逻辑如下&#xff1a; /***************************************动态使用cell核心逻辑开始 **************************************///计算所有cell的坐标信息 …

《python编程从入门到实践》day38

# 昨日知识点回顾 定义、迁移模型Entry # 今日知识点学习 18.2.7 Django shell 每次修改模型后&#xff0c;看到重启后的效果需要重启shell&#xff0c;退出shell会话Windows系统按ctrlZ或者输入exit() 18.3 创建页面&#xff1a;学习笔记主页 创建页面三阶段&#xf…

【Windows系统】解决Intel 6代CPU安装win7系统过程中无法操作键盘鼠标的问题

问题 微软表示&#xff0c;从 2016 年 7 月 17 日起&#xff0c;新的 Intel、AMD 和Qualcomm 处理器将仅支持 Windows 10&#xff0c;不再支持 Windows 7 和 8.1。因此&#xff0c;Intel 6代以后的CPU因为没有USB驱动无法完成win7系统的安装。 下文核心思想是通过老毛桃PE系统…

AI PC 的曙光:微软大胆出击与苹果竞争

AI PC 的曙光&#xff1a;微软大胆出击与苹果竞争 AI PC 的曙光&#xff1a;微软大胆出击与苹果竞争 概述 微软已正式进入 AI PC 时代&#xff0c;并且毫不避讳地直接向苹果的 MacBook 发起攻击。随着代号为“Copilot”的笔记本电脑的推出&#xff0c;微软准备彻底改变我们与…

Android 实现竖排文本(垂直方向显示)

Android 实现竖排文本-垂直方向显示 前言效果图代码实现方式一 Custom View1. 自定义视图 VerticalTextView2. 在xml布局文件中使用3. 设置文本内容 方式二 使用 TextView 的 rotation属性方式三 使用带有跨距文本的TextView1. 自定义视图 VerticalTextView2. 在xml布局文件中使…

ML307R OpenCPU UART使用

一、串口使用流程图 二、串口相关函数介绍 三、实现串口收发 一、串口使用流程图 OneMO ML307R模组提供了2路UART给开发者用于通讯开发&#xff0c;以及1路DBG UART用于log的打印。UART Demo示例可以在SDK&#xff1a;examples\uart\src\cm_demo_uart.c中查看。 串口使用流…

视频号小店的保证金是多少钱?2024最新收费标准,一篇了解!

哈喽~我是电商月月 现实社会&#xff0c;干什么都需要交钱&#xff0c;就连上班&#xff0c;路费也得掏钱 想要入驻视频号小店&#xff0c;在视频号里卖货赚钱&#xff0c;就要缴纳类目保证金 那到底要缴多少钱呢&#xff1f; 今天&#xff0c;月月就把最新的收费标准分享给…