大小端序与端序转换

最近在做客户项目的时候,遇到了不同厂家的安防相机输出的数据大小端序不一致的情况,导致在使用同一种方式处理时,出现了错误。虽然问题已经解决,还是顺手把大小端序的知识简单梳理一下。

1. 大端序和小端序的概念

我们知道,计算机在存储数据时,是以字节为单位的,每个地址对应一个字节。但在现代编程语言中,使用的数据类型往往需要1、2、4、8个字节,那么就涉及到这些数据在内存中如何存储的问题。除此之外,不同位数的处理器(如16位、32位、64位)其寄存器的宽度也不同,因此也会涉及到字节顺序的问题。不同的处理器或者不同的应用对字节顺序的不同处理,就催生出了大小端序的概念。

所谓大端序(Big-endian),即在数据存储时,数据的高位字节存放在内存的低地址端,而数据的低位字节存放在内存的高地址端;

小端序(Little-endian)则相反,数据的高位字节存放在内存的高地址端,数据的低位字节存放在内存的低地址端。

注意,无论大端序还是小端序,单个字节内部的bit顺序是一致的。

大端序与人们对数字的书写顺序一致,例如一个32位的整型数据0x12345678,如果使用大端序,其在内存中的存储顺序如下,其中p表示起始地址。

如果将0x12345678使用小端序存储,则存储顺序如下图所示:

一般情况下,我们常用的X86架构的处理器都是小端序,而通信协议一般选择大端序(因此,大端序也常称为网络字节序),当然,有些ARM处理器可以工作在大端模式,也可以工作在小端模式。

2. 大小端序之间的转换

了解了大小端序的概念,那么我们就可以针对具体的端序问题,通过转换的方式进行解决。在本文一开始提到,两个厂商的相机输出的字节序不一致的问题,表现为32位float型数据,传输到本地服务器时,有一家相机的数据依然是按照大端序存储的,因此导致运算出错。我们尝试对数据进行转换。由于是float类型,float类型在内存中的存储较复杂,因此我们借助联合体,通过对32位int型数据的转换,实现对32为float类型数据的转换。

union union32IntFloat
{
	int32_t i_32;
	float f_32;
};

/* Swap bytes order for int32_t value */
int32_t bytes_swap_int32(int32_t int_value)
{
	int32_t int_swapped = ((int_value & 0x000000FF) << 24 |
							(int_value & 0x0000FF00) << 8 |
							(int_value & 0x00FF0000) >> 8 |
							(int_value & 0xFF000000) >> 24);
							
	return int_swapped;
}

/* Swap bytes order for float32 value */
float bytes_swap_float32(float value)
{
	union32IntFloat u_value;
	u_value.f_32 = value;
	
	u_value.i_32 = bytes_swap_int32(u_value.i_32);
	
	return  u_value.f_32;  
}

测试程序:将一个大端序存放的数字转成小端序之后输出:

int main()
{
	float ori_float = -16223553;   //F4 F7 8D 41
	float swapped_float = bytes_swap_float32(ori_float);

	std::cout << "Before swap: " << ori_float << ", after swap: " << swapped_float << std::endl;

	return 0;
}

执行结果如下:

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值