C++大端小段的判断和转换

C/C++ 大小端字节序的判断和转换 大小端原理示意图 int x = 0x01; 地址增长方向 -----> 小端序,低位位于低字节处 +----+----+----+----+ |0x01|0x00|0x00|0x00| +----+----+----+----+ A | &x 大端序,高位处于低字节处 +----+----+----+----+ |0x00|0x00|0x00|0x01| +----+---- 阅读详情

当前的存储器,多以byte为访问的最小单元,当一个逻辑上的地址必须分割为物理上的若干单元时就存在了先放谁后放谁的问题,于是端(endian)的问题应运而生了,对于不同的存储方法,就有大端(big-endian)和小端(little- endian)两个描述。

字节排序按分为大端和小端,概念如下

大端(big endian):低地址存放高有效字节

小端(little endian):低字节存放地有效字节

现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian,ARM则同时支持 big和little,网络编程中,TCP/IP统一采用大端方式传送数据,所以有时我们也会把大端方式称之为网络字节序。

特别需要注意的是,C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而 JAVA编写的程序则唯一采用big endian方式来存储数据。这里我就只讨论C/C++语言的情况。

1.大端和小端的方式及判断

举个例子说明,我的机子是32位windows的系统,处理器是AMD的。对于一个int型数0x12345678,为方便说明,这里采用16进制表示。这个数在不同字节顺序存储的CPU中储存顺序如下:

0x12345678   16进制,两个数就是一字节

高有效字节——>低有效字节: 12 34 56 78

          低地址位     高低址位

大端:  12  34        56   78

小端: 78  56        34   12

下面验证下本机CPU属于哪种字节存储顺序。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
using  namespace  std;
 
typedef  unsigned int  UINT ;
typedef  unsigned char  UCHAR ;
 
int  main()
{
     UINT  i=0x12345678;
     cout<<hex<<i<<endl;
     UCHAR  *p = ( UCHAR *)&i;          //将i的地址传给数组指针p,实际上p指向的地址是i在内存中存储的第一个字节,大端就是0x12,小端就是0x78
     if ((*p==0x78)&(*(p+1)==0x56))       
         cout<< "小端" <<endl;
     else  if ((*p==0x12)&(*(p+1)==0x34))
         cout<< "大端" <<endl;
     else
         cout<< "这是神马字节顺序呢?" ;
     return  0;
}

调试显示时小端,我用的机子字节存储为小端方式。

2.大端和小端的字节转换

当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序(即大端方式)后再进行传输。此外用C/C++在小端方式的机器上编写的程序与java程序互通时也要进行大端和小端的转换。

这里所谓转换就是改变字节的排序,使交互时数据保持一致。举一个例子,还是16进制表示的数0x12345678,在小端机器上排序为0x78563412,当内存中这样的数传输时,在大端方式下就是0x78563412这个值,与原值不同,要想与原值相同,在传输前,在大端方式下就该是0x12345678,这时原数在内存中为0x12345678,即将原数据0x12345678在内存存储序列为0x12345678,也就是要转换成大端方式。

要传输值:12 34 56 78

不转换时,小端:78 56 34 12

转换为大端:12 34 56 78

根据上面的大端和小端字节排序,可以方便的用移位运算完成转换功能。从小端转到大端代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
 
using  namespace  std;
 
typedef  unsigned int  UINT ;
typedef  unsigned char  UCHAR ;
 
int  main()
{
     UINT  i=0x12345678;
     cout<<hex<<i<<endl;
     UCHAR  *p = ( UCHAR *)&i;
     UINT  num,num1,num2,num3,num4;
     num1=( UINT )(*p)<<24;
     num2=(( UINT )*(p+1))<<16;
     num3=(( UINT )*(p+2))<<8;
     num4=(( UINT )*(p+3));
     num=num1+num2+num3+num4;
 
     cout<< "num1:" <<hex<<num1<<endl;     //看num1的16进制表示,下同
     cout<< "num2:" <<hex<<num2<<endl;
     cout<< "num3:" <<hex<<num3<<endl;
     cout<< "num4:" <<hex<<num4<<endl;
     cout<< "num:" <<hex<<num<<endl;
 
     unsigned char  *q = (unsigned char *)&num;
     if ((*q==0x78)&(*(q+1)==0x56))         
         cout<< "小端" <<endl;
     else  if ((*q==0x12)&(*(q+1)==0x34))
         cout<< "大端" <<endl;
     else
         cout<< "这是神马字节顺序呢?" ;
     return  0;
}

至于说(UINT)(*p)为什么要移24位,其实是很好理解的,将0x00000012变成0x12000000,不就是向左移24位吗。

当然,向上面这样写时为了方便理解,可以更简单的写一个函数用于完成上面的转换功能,函数如下:

1
2
3
4
5
UINT  EndianConvertLToB( UINT  InputNum) {
     UCHAR  *p = ( UCHAR *)&InputNum;
     return ((( UINT )*p<<24)+(( UINT )*(p+1)<<16)+
                (( UINT )*(p+2)<<8)+( UINT )*(p+3));
}

同样的原理适用于大端转小端,但是大端转小端时移位有差别,函数如下:

1
2
3
4
5
UINT  EndianConvertBToL( UINT  InputNum) {
     UCHAR  *p = ( UCHAR *)&InputNum;
     return ((( UINT )*p)+(( UINT )*(p+1)<<8)+
                (( UINT )*(p+2)<<16)+( UINT )*(p+3)<<24);
}



更一般的做法如下:

bool is_big_endian()
{
	unsigned short test = 0x1234;
	if(*( (unsigned char*) &test ) == 0x12)
		return true;
	else
		return false;
}
int big_endian_string_to_int(const string& str)
{
	if (str.length() <=0)
	{
		return -1;
	}
	int a=0;
	int i=0;

	a+= str[i];
	while (++i < str.length())
	{
		a=a<<8;
		a += str[i];
	}
	a += str[i];
	
	return a;
}
int web_string_to_int(const char* array,const unsigned len)
{
	int a = 0;
	string str(array,array+len);

	if (is_big_endian()) //大端机
	{
		return big_endian_string_to_int(str);
	}
	else // 小端机转换为整数
	{
		reverse(str.begin(),str.end());
		return big_endian_string_to_int(str);
	}
	return a;
}
int main(int, char *[])
{
	
	char a[4]={0x12,0x34,0x56};
	cout<<::hex<<web_string_to_int(a,3)<<endl;
	

	return 0;
};

程序输出:563412


c++的大端小端 大端:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中。在x86下,考虑到在内存中是按照字节为单位进行数据排布,那么会把0x12,0x34这2个值按照大端进行存储。例1:16位宽的数0x1234地址(由低到高)0x4000(低地址)0x4001(高地址)(大端)存放内容0x12(高位)0x34(低位)例2:32位宽的数0x12345678在x86下,考虑到在内存中是按照字节为单位进行... 阅读详情

相关推荐

大端存储 & 小端存储

这篇介绍一下内存中存放数据的两种模式:大端存储(或大端模式,Big-Endian) & 小端存储(或小段模式,Little-Endian),这两种存储模式在通信或者socket编程里面可能用的比较多 如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢 大端存储(Big-Endian) 数据的高字节存储在低地址中,数据的低字节存储在高地址中 如: int a = 1; // int在内...

xiao_ma_nong_last的博客 330

大小端及转换(C++)

1. 基本概念 大小端表示数据在存储器中存放的顺序。 大端模式: 数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放; 小端模式:数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。 假如在一段内存中存储如下数据 uint8_t A = 0xA1; uint8_t

休息一下接着来的博客 1万+

Socket网络编程如何将浮点型数据转换为整形并在接收端进行恢复

概述:在网络编程中将浮点型数据转换为整形,用于传输,然后在接受端进行恢复。注意该操作是按字节进行操作的,在转换过程中不必关闭整型中间值,重点是将浮点型数据转换后,能在接收端能正确恢复成浮点型数据。 浮点型转为整型 int double2int(double m_fd) { int nIntMax = 0; int nInt, n_fd; nIntMax = 1 << 31; ...

Lee_Blog 1213

c++大小端转换

大小端表示数据在存储器中存放的。:数据的高字节保存在内存的低地址中,低字节则保存在内存的高地址中。:数据的高字节保存在内存的高地址中,低字节保存在内存的低地址中。如下例:说明uint8_t C中的0xC1为高字节,0xC2为低字节。在上图中,对于单字节(8位)数据在大小端模式下没有任何区别。

lucust的博客 5009

C/C++ 工具函数 —— 大端模式和小端模式的互换

uint32_t swap_endian(uint32_t val) { val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); return (val << 16) | (val >> 16); }

我不是码农的博客~~~ 801

告别‘小爱同学’:用ESP32-S3和esp-sr SDK,从零打造一个离线语音助手(含完整代码)

本文详细介绍了如何利用ESP32-S3芯片和esp-sr SDK从零构建一个离线语音助手,涵盖硬件选型、声学设计、SDK配置及低功耗优化等关键步骤。通过实战案例和完整代码,帮助开发者实现自定义唤醒词和命令词,打造低成本、高隐私的本地语音控制解决方案。

weixin_29041195的博客 371

Union的内存模型-大端模式和小段模式

// // main.cpp // C++Test23 // #include <iostream> #include <math.h> using namespace std; union A { int i; char c[2]; }; bool IsBigEndian() { int a = 0x1234; char b =...

LANGZI7758521的专栏 310

实战游戏项目管理1-规划篇

1、前言 做研发管理10多年,进游戏行业8年,经验下来项目管理就是一门技术,结合不同行业不同项目加以不同管理方法,但原理基本一样,这里总结下游戏项目的管理一些实操方法 一般游戏确定立项前都需要做,项目预研产出一个游戏Demo,通过公司的立项评审,这个过程的项目管理相对简单一般由制作人或其他项目经理兼任,只有控制好总体时间与成本就好,这里按立项后开始讲。 2、游戏项目规划 ...

pengdali的专栏 2万+

小端模式和大端模式的区别与C++代码检测

序言:当同一台主机上的两个进程(一个由c语言编写,另一个由Java编写)通信或者两台使用不同字节序的主机之间传送数据时,若字节序不同,则发送的数据和接受的数据不一样。因此需要进行小端字节序(小端模式)、大端字节序(大端模式)的识别与转换。以下以32位机器讲解。 大端字节序(也称 大端模式):指一个整数的高位字节(23~31bit)存储在内存的低地址处,低字节(0 ~ 7bit)存储在内存的高地址处。 小段字节序(小端模式):指一个整数的高位字节存储在 内存 的高地址处,低字节存储在内存的低地址处。

fei 465

永磁同步电机定子槽型设计实战:从梨形槽到矩形槽的NVH优化之路

本文深入探讨了永磁同步电机定子槽型设计在NVH优化中的关键作用,对比了梨形槽与矩形槽的性能差异。通过Ansys Maxwell仿真和实际案例,揭示了矩形槽在提升槽满率、降低电磁噪声方面的优势,并总结了五大设计黄金法则,为电机设计工程师提供了实用指导。

weixin_28740299的博客 493

Lattice HSB 相机方案

Lattice与NVIDIA合作的HSB相机方案提供低延迟视觉处理方案。该方案采用CertusPro-NX/Avant-E FPGA接收多路相机数据,通过10G/25G以太网直连GPU显存,实现端到端延迟<17ms、CPU占用<1%的高效处理。方案支持PTP同步、多种协议,适用于医疗、工业、车载等领域。相比传统方案,开发效率提升10倍以上,具有显著性能优势。部署需Lattice FPGA板、10G/25G交换机和Holoscan SDK等软硬件支持。

xzjiang_365的博客 755

大端字节序和小端字节序详细介绍

摘要: 字节序是数字在内存或串口传输中的存储顺序,分为大端序(高字节在前,如工业设备)和小端序(低字节在前,如Windows电脑)。若不转换,串口通信时会导致数值解析错误(如0x1234被误读为0x3412)。通过C++联合体(union)可快速判断系统字节序:若首字节为低字节(0x34)则为小端,反之为大端。**关键点:**串口通信必须进行字节序转换,否则数据解析错误! (字数:149)

qq_63683271的博客 650

X书关键词协议搜索

【代码】X书关键词协议搜索。

Codeooo 博客 6377

c++ uin8_t[4]到float类型转换技巧和细节

类型转换时的那些坑

qq_61971313的博客 724

PX4从放弃到精通(二十二):日志

文章目录前言一、下载日志二、ulog转CSV三、利用flightplot软件分析PX4的ulog日志1 windos安装2 ubuntu18.04安装四、使用PlotJuggler分析PX4日志五、设置日志记录条件六、添加自定义日志消息 前言 PX4 1.10以上固件 QGC 一、下载日志 将飞控链接地面站,在下图页面点击“刷新”,即可看到保存的日志(前提是要有TF卡) 选择需要下载的日志,点击右侧的“下载”,然后选择目录即可进行下载,如果想擦除所有的日志,可以点击右侧的“擦除全部” 二、ulog转CS

超维空间科技的博客 6796

使用Microsoft Print to PDF进行编程:创建PDF文件的简单方法

Microsoft Print to PDF是一种内置于Windows操作系统中的功能,它允许我们通过打印操作将任何可打印的内容保存为PDF文件。然后,我们使用Microsoft Print to PDF打印机进行打印操作,并将输出文件保存为指定的PDF文件。使用Microsoft Print to PDF功能是一种方便且简单的方法来创建PDF文件,无论是在个人使用还是在企业开发中,它都可以提供良好的支持和灵活性。请注意,如果你使用的是其他编程语言,你可以根据相应的打印机接口或库来实现类似的功能。

TechSavant的博客 1635

大小端定义及判断

大端,小端又名网络字节序,主机字节序。高位高存,低位低存是小端,复合人们的视觉体验,不用改变位置,如0x0102,在内存的存储位置也是 01 02。而大段相反,复合逻辑,为02 01。如今网络传输,keli5c等使用大端,x86系列使用小段。 unp中有一个程序用来判断大小端: //endian_check.cpp #include<iostream> using namespa...

h17802535087的博客 432

QCC51XX---人机接口设备协议( HID)

QCC51XX---人机接口设备协议( HID)

weixin_42162924的博客 819

大端序 小端序 Java_大端法、小端法、网络字节序 转

关于字节序(大端法、小端法)的定义《UNXI网络编程》定义:术语“小端”和“大端”表示多字节值的哪一端(小端或大端)存储在该值的起始地址。小端存在起始地址,即是小端字节序;大端存在起始地址,即是大端字节序。也可以说:1.小端法(Little-Endian)就是低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端。2.大端法(Big-Endian)就是高位字节排放在内存的低地址...

weixin_33945759的博客 495

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

关于C++的一些问题的整理

1 如何判断数据在C++的栈中是以大端模式还是小端模式cu

a1037488611的专栏 497

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

大端与小端

0. 如何判断系统是大端还是小端? 在/usr/include中(包括子目录)查找字符串BYTE_ORDER(或_BYTE_ORDER,_BYTE_ORDER),确定其值。这个值一般在endian.h或machine/endian.h文件中可以找到,有时在feature.h中,不同的操作系统可能有所不同。一般来说,Little Endian系统BYTE_ORDER(...

weixin_34072857的博客 190

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

判断机器大小端问题

大端存储:即高字节存储在低地址处,即高位先存,大端也叫“高尾端” 小段存储:即低字节存储在高地址处,即低位先存,小端也叫“低尾端” 大端存储:例如0x11223344,则44就是尾端,存储地址假如从0~4,则当存储这个数据时,将依次从低地址0向高地址4存储,且按照11~44的顺序存储就叫大端存储。 小段存储:例如0x11223344,则44就是尾端,存储地址假如从0~4,则当存储这个

Mr_Dictator的博客 362

union关键字和取类成员函数地址的方法

union关键字 union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址。例子如下: union StateMachine {     char character;     int number;     char *str;

Jedihy的博客 1294

C++socket编程(三)3.2 创建TCPServer设置服务信息并讲解网络字节序

一:创建TCPserver 如下代码: 创建TCPserver设置服务信息代码如下 int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("create socket failed!\n"); return -1; } unsigned short port = 8080; if (argc > 1) { port = atoi(argv[1]); } //创建 sockaddr_

weixin_43907175的博客 1106

数据传输踩坑——确认数据大小端

大小端 小段存储: 高对高 大端存储:低对高 判断大小端 JVM default big-endian ,c++ default little-endian int a = 1; if (((char*)&a)[3] ==1){ //big-endian return 1; } else{ //little-endia...

Tom_sky的博客 622

c++和java通讯大小端问题处理_Java与C/C++网络通信时的数据转换

最近做了一款Android应用,需要和PC端通过socket传递数据。PC端是用C++开发的,为了方便传输,在发送之前都将数据转化为字节数组。本以为可以万事大吉,可是过程还是会有一些问题。下面是我遇到的几个问题以及解决方案,这里做一个简单的记录,也希望大家遇到后能够快速解决,同时欢迎各位补充指正~Java Socket的接收与发送首先我们会建立一个socket连接,然后从中获取InputStrea...

weixin_39658019的博客 78
上一篇: C++迭代器配接器(实现容器、文件、控制台之间的I/O )
下一篇: libprotobuf ERROR google/protobuf/wire_format.cc:1059
C++程序员Carea
博客等级 码龄18年 1590粉丝 878原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值