首页 > 编程语言 >【C++】十六进制数据的字节序排列问题、大小端

【C++】十六进制数据的字节序排列问题、大小端

时间:2024-11-19 17:15:50浏览次数:3  
标签:小端 十六进制 字节 0x01 C++ 发送 0x30 低字节

十六进制数据的字节序排列问题,涉及到 大小端(Endianness) 的概念。 包括它与大小端存储方式的关系。


1. 十六进制数据在内存中的存储

定义的数据
#define FRAME_TYPE_PARAM_SET 0x3001
  • 0x3001 是一个 16 位(2 字节)整数
  • 在内存中,0x3001 的存储方式依赖于系统的字节序:
    • 小端模式(Little Endian):低字节存储在低地址,高字节存储在高地址。
    • 大端模式(Big Endian):高字节存储在低地址,低字节存储在高地址。
两种存储方式的内存布局

0x3001 为例,16 位数值可以拆分为两个字节:

  • 高字节:0x30
  • 低字节:0x01
模式存储顺序内存布局
小端低字节 -> 高字节0x01 0x30
大端高字节 -> 低字节0x30 0x01

2. 小端与大端在数据发送中的影响

发送的数据

当你发送 0x3001 时:

  • 如果主机采用 小端模式(如 x86 处理器),数据将以小端格式排列发送:
    • 先发送低字节 0x01,再发送高字节 0x30
  • 如果主机采用 大端模式,数据将以大端格式排列发送:
    • 先发送高字节 0x30,再发送低字节 0x01
监控工具显示

监控工具通常直接按照字节顺序显示数据:

  • 如果是 小端发送
    • 数据在监控中会显示为 0x01 0x30,即你看到的 0130
  • 如果是 大端发送
    • 数据在监控中会显示为 0x30 0x01,即与定义一致。

3. 如何确认主机的字节序?

可以通过以下代码确认主机是小端还是大端:

#include <iostream>

int main() {
    uint16_t value = 0x1234;  // 定义一个16位数
    uint8_t* ptr = reinterpret_cast<uint8_t*>(&value);

    if (*ptr == 0x34) {
        std::cout << "Little Endian (小端)" << std::endl;
    } else {
        std::cout << "Big Endian (大端)" << std::endl;
    }

    return 0;
}
  • 如果输出 Little Endian,说明主机是小端模式(大多数处理器如 x86、ARM 默认是小端)。
  • 如果输出 Big Endian,说明主机是大端模式。

4. 如何解决发送时的字节序问题?

如果协议要求以 大端模式 发送数据(即高字节在前),而你的主机是 小端模式,需要在发送之前进行字节序转换。

使用系统提供的字节序转换函数

在 POSIX 系统(Linux、Windows)中,可以使用以下函数:

  • htons:将 16 位整数从主机字节序转换为网络字节序(大端)。
  • htonl:将 32 位整数从主机字节序转换为网络字节序(大端)。

示例:

#include <arpa/inet.h>  // 或 winsock2.h

uint16_t value = 0x3001;
uint16_t bigEndianValue = htons(value);  // 转换为大端
手动实现字节序转换

也可以通过位运算手动转换:

uint16_t toBigEndian(uint16_t value) {
    return (value >> 8) | (value << 8);
}

5. 总结

现象
  • 代码中定义的 0x3001 在内存中是按字节存储的。
  • 主机是小端模式时,低字节(0x01)会在前,发送时的顺序也是低字节在前,因此VS监控工具显示 0130
涉及知识点
  • 大小端模式(Endianness)
    • 小端:低字节在前(如 0x01 0x30)。
    • 大端:高字节在前(如 0x30 0x01)。
  • 网络字节序
    • 大端是网络协议的通用字节序。
    • 如果主机是小端,需要在发送前进行字节序转换。
现象
  • 如果协议要求大端格式,使用字节序转换函数(如 htons)确保发送的数据符合协议。
  • 如果协议明确允许小端格式,可以直接发送,不需要额外处理。

标签:小端,十六进制,字节,0x01,C++,发送,0x30,低字节
From: https://blog.csdn.net/weixin_44939430/article/details/143889217

相关文章

  • C++编程:通过多线程与协程优化阻塞型任务的调度性能
    文章目录0.引言1.多线程VS多线程+协程1.1示例1:使用传统的多线程进行矩阵乘法1.2.示例2:使用协程优化阻塞型任务3.分析与对比0.引言我们知道:多线程:适用于处理计算密集型任务或IO操作较少的场景,但会因为线程切换和创建销毁的开销而影响性能。协程:适用于处......
  • 实验4 C++
    任务2:GradeCalc.cpp1#pragmaonce2#include<iostream>3#include<vector>4#include<string>5#include<algorithm>6#include<numeric>7#include<iomanip>89usingstd::vector;10usingstd::......
  • C++ 学习笔记(1):STL、Vector 与 Set
    背景最近在尝试入坑蓝桥杯,于是先从C++开始学起,这里记个笔记。这里我的笔记是跟着这个教程来的。沙比学校天天整些屁事都没什么空折腾。前言笔者是JS/TS写的比较多,以前写过C但是有点忘了,所以文章里都是和JS进行对比着方便快速理解。同时其实我还有几个小问题,嘻嘻。没......
  • C++中的友元函数和友元类&友元的作用及注意事项
    1.C++中的友元函数和友元类友元函数:友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。通常,同一个开发者会出于技术和非技术的原因控制类的友元和成员函数,否则在更新类时,还需要征得其他部分的拥有者的同意。友元函数在定义上和调用......
  • 打卡信奥刷题(264)用C++信奥P2010[普及组/提高] [NOIP2016 普及组] 回文日期
    [NOIP2016普及组]回文日期题目背景NOIP2016普及组T2题目描述在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。牛牛习惯用888位数字表示一......
  • 详解 C++ 的内存序模型
    详解C++的内存序模型C++提供了内存序模型来控制多线程程序中不同线程对共享内存的访问顺序。最常用的是顺序一致性内存模型(memory_order_seq_cst),但它也提供了其他模型(如memory_order_relaxed)以优化性能。一、顺序一致性内存模型(memory_order_seq_cst)定义顺序一致性......
  • Python 基于C++ & python的键盘记录器发送指定邮箱
    Python基于C++&python的键盘记录器发送指定邮箱1.简介:采用c++与python语言相结合的方法,c++负责采集键盘操作记录到文本,python脚本实时将文本内容发送至指定邮箱。资源文件已打包,可设置开机自启动。2.kb.cpp键盘记录实现代码:#include<iostream>#include<stdio.h>......
  • Python将IPv4地址转换成十进制、十六进制
    importsocketimportstruct#定义IP地址ip='192.168.66.21'#将IP地址转换为十进制ip_decimal=struct.unpack("!I",socket.inet_aton(ip))[0]#将十进制转换为十六进制ip_hex=hex(ip_decimal)#输出结果print(f"IP地址:{ip}")print(f"十进制:{......
  • 实现简易计算器 网格布局 QT环境 纯代码C++实现
    问题:通过代码完成一个10以内加减法计算器。不需要自适应,界面固定360*350。"="按钮90*140,其它按钮90*70。参考样式#defineDEFULT_BUTTON_STYLE"\QPushButton{\color:#000000;\border:1pxsolid#AAAAAA;\border-radius:0;\background-color:#FFFFFF;......
  • 字节跳动精选20道产品经理面试题分析回答
    前言分享20道字节跳动产品经理的面试题,产品经理的面试很多会跟项目强关联,比如面试电商产品经理,就要多聊电商的业务,所以我们选了一些比较通用的,面试题及我们的分析回答。0120道面试题1)自我介绍。2)为什么做产品经理?3)这么多年的工作经验,你对产品经理有什么新的认知?4)你觉......