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

简介: 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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

“大数据建模、分析、挖掘技术应用研修班”的通知!

随着2015年9月国务院发布了《关于印发促进大数据发展行动纲要的通知》&#xff0c;各类型数据呈现出了指数级增长&#xff0c;数据成了每个组织的命脉。今天所产生的数据比过去几年所产生的数据大好几个数量级&#xff0c;企业有了能够轻松访问和分析数据以提高性能的新机会&am…

夏日采摘季,视频智能监控管理方案助力智慧果园管理新体验

5月正值我国各地西瓜、杨梅、大樱桃、油桃等水果丰收的季节&#xff0c;许多地方都举办了采摘旅游活动&#xff0c;吸引了众多游客前来体验采摘乐趣。随着采摘的人流量增多&#xff0c;果园的管理工作也面临压力。 为了提升水果园采摘活动的管理效果&#xff0c;减少人工巡查成…

harbor 认证

Harbor 认证过程 Harbor以 Docker Registry v2认证为基础&#xff0c;添加上一层权限保护。1.v2 集成了一个安全认证的功能&#xff0c;将安全认证暴露给外部服务&#xff0c;让外部服务去实现2.强制用户每次Docker pull/push请求都要带一个合法的Token&#xff0c;Registry会…

基于jeecgboot-vue3的Flowable新建流程定义(一)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、vue3版本因为流程分类是动态的&#xff0c;不再固定了&#xff0c;所以新建的时候需要选择建立哪种流程类型的流程 代码如下&#xff1a; <!-- 选择模型的流程类型对话框 -->&…

JDBCTemplate介绍

Spring JDBC Spring框架对Spring的简单封装。提供一个JDBCTemplate对象简化JDBC开发 *步骤&#xff1a; 1、导入jar包 2、创建JDBCTemplate对象。依赖于数据源DataSource *JdbcTemplate templatenew JdbcTemplate(ds); 3、调用JdbcTemplate的方法来完成CRUD的操作 *update()&…

【实战教程】使用Spring AOP和自定义注解监控接口调用

一、背景 随着项目的长期运行和迭代&#xff0c;积累的功能日益繁多&#xff0c;但并非所有功能都能得到用户的频繁使用或实际上根本无人问津。 为了提高系统性能和代码质量&#xff0c;我们往往需要对那些不常用的功能进行下线处理。 那么&#xff0c;该下线哪些功能呢&…

代码随想录-Day18

513. 找树左下角的值 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 方法一&#xff1a;深度优先搜索 class Solution {int curVal 0;int curHeight 0;public int findBottomLeftValue(TreeNode roo…

GitLens或者Git Graph在vscode中对比文件历史变化,并将历史变化同步到当前文件中

有时候我们上周改的代码&#xff0c;现在想反悔把它恢复过来&#xff0c;怎么办&#xff1f;&#xff1f;&#xff1f;很好&#xff0c;你有这个需求&#xff0c;说明你找对人了&#xff0c;那就是我们需要在vscode中安装这个插件&#xff1a;GitLens或者Git Graph&#xff0c;…

做抖店四年来的经验分享,想做抖店的多看看,给你揭露真正的抖店

大家好&#xff0c;我是电商花花。 我做抖音小店从21年就已经开始了&#xff0c;中间一直都没断过&#xff0c;一直都抖店无货源&#xff0c;从刚开始的一家店铺&#xff0c;到现在的80多家店铺&#xff0c;不断完善和总结我们做店的方法。 在我看来做抖音小店现在很简单&…

Linux服务升级:Twemproxy 升级 Redis代理

目录 一、实验 1.环境 2.多实例Redis部署 3.Twemproxy 升级Redis代理 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本软件IP备注CentOS7.9Twemproxy192.168.204.200 Redis代理 Redis127.0.0.1:6379第一个Redis实例 Redis127.0.0.1:6380第二个…

别被“涨价“带跑,性价比才是消费真理

文章来源&#xff1a;全食在线 “再不好好赚钱&#xff0c;连方便面也吃不起了。”这是昨天在热搜下&#xff0c;一位网友的留言。而热搜的内容&#xff0c;正是康师傅方便面即将涨价的消息。 01 传闻初现 昨天上午&#xff0c;朋友圈就有人放出康师傅方便面要涨价的消息&am…

Py之llama-parse:llama-parse(高效解析和表示文件)的简介、安装和使用方法、案例应用之详细攻略

Py之llama-parse&#xff1a;llama-parse(高效解析和表示文件)的简介、安装和使用方法、案例应用之详细攻略 目录 llama-parse的简介 llama-parse的安装和使用方法 1、安装 2、使用方法 第一步&#xff0c;获取API 密钥 第二步&#xff0c;安装LlamaIndex、LlamaParse L…

从ZooKeeper切换到ClickHouse-Keeper,藏着怎样的秘密

本文字数&#xff1a;7772&#xff1b;估计阅读时间&#xff1a;20 分钟 作者&#xff1a;博睿数据 李骅宸&#xff08;太道&#xff09;& 小叮当 本文在公众号【ClickHouseInc】首发 本系列前两篇内容&#xff1a; 从ES到ClickHouse&#xff0c;Bonree ONE平台更轻更快&a…

API攻击呈指数级增长,如何保障API安全?

从远程医疗、共享汽车到在线银行&#xff0c;实时API是构建数字业务的基础。然而&#xff0c;目前超过90%的基于Web的网络攻击都以API端点为目标&#xff0c;试图利用更新且较少为人所知的漏洞&#xff0c;而这些漏洞通常是由安全团队未主动监控的API所暴露&#xff0c;致使API…

【设计模式】JAVA Design Patterns——Callback(回调模式)

&#x1f50d;目的 回调是一部分被当为参数来传递给其他代码的可执行代码&#xff0c;接收方的代码可以在一些方便的时候来调用它。 &#x1f50d;解释 真实世界例子 我们需要被通知当执行的任务结束时。我们为调用者传递一个回调方法然后等它调用通知我们。 通俗描述 回调是一…

K8s 部署prometheus

文章目录 K8s 部署prometheuskube-prometheus 部署部署流程安装卸载补充 K8s 部署prometheus kube-prometheus 部署 kube-prometheus 是 github 上开源的整合了 prometheus alertmanager granfana 等监控工具的项目&#xff0c;github地址 如果github 访问不了的也可以选择 g…

忘记“也是一门学问:机器如何忘记自己学到的知识?

在信息时代&#xff0c;我们常常希望人工智能能够学到更多的知识&#xff0c;变得更加智能。但你是否想过&#xff0c;有时候让机器"忘记"一些它学到的东西&#xff0c;也是一件很重要的事&#xff1f; 随着用户隐私保护意识的提高和相关法律法规的出台&#xff0c;…

张大哥笔记:穷人都在拼命挣钱,而富人都在努力让自己更值钱

最近行业大佬&#xff0c;纷纷网红化&#xff0c;比如周鸿祎&#xff0c;雷军&#xff0c;刘强东纷纷下场&#xff01; 大佬当网红&#xff0c;图啥&#xff1f;当然是图钱了。 大佬都很精的&#xff0c;他们老早就运用媒体的传播杠杆&#xff0c;把自己热度炒起来。 在不断…

Opencompass模型评测教程

模型评测 模型评测非常关键&#xff0c;目前主流的方法主要可以概括为主观评测和客观评测&#xff0c;主观评测又可以分为两种形式&#xff1a;人工判断或者和模型竞技场。客观评测一般采用评测数据集的形式进行模型评测。本教程使用Opencompass工具进行对Internlm2-7b模型进行…

通过Wirtinger流进行相位恢复:理论与算法

文章目录 1. 简介2. 算法描述2.1 初始化(Initialization)2.2 迭代更新(Iterative Updates)2.3 学习率调整&#xff08;Learning Rate Adjustment&#xff09; 3. 代码实现3.1 一维信号测试 &#xff08;Gaussian model&#xff09;3.2 一维信号测试 &#xff08;Coded diffract…