解决大小端与自定义协议不兼容问题

本文探讨了在遇到大小端模式与自定义协议不兼容时的解决方案,包括宏定义、异或、字节数组、联合体等方法,并分析了各种方法的优缺点,如可读性、调用简便性和执行效率。强调在协议设计时考虑数据可读性,推荐使用宏定义和联合体方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

  上一篇中遇到一个问题:小端模式的必然性(先低字节后高字节) 和 自定义协议的不可更改性,导致无法衔接。而本来可以避免的(定义协议的时候考虑到),否则就会导致代码的可读性下降,多上一大堆语句,可维护性下降,(报文解包和打包时都需要进行高低字节翻转)。

  既然遇到问题了,那就该反馈问题,实在不行就解决/消化问题:解决十六位数 和 三十位数的 高低位交换。

  本来还有点儿发愁该怎么实现好,结果一下子找到了四五种解决方式,着实有点儿出乎意料。
主要参考这篇文章:多字节变量的高低字节交换 和 蓝牙工程中的一些代码。

宏定义方式

  通过移位方式实现高低位交换。

#define SWAP16(a)   ((a)<<8)|((a)>>8)
#define SWAP32(b)   ((b)<<24)|(((b)<<8)&0xff0000)|(((b)>>8)&0xff00)|((b)>>24)

// 对于SWAP32(b), 表达式有点儿复杂,可以通过一个例子来说明
// 假设b 为 0x12345678
// 第一个子表达式 :0x78000000
// 第二个子表达式 :0x34567800  -->  0x00560000
// 第三个子表达式 :0x00123456  -->  0x00003400
// 第四个子表达式 :0x00000012
// SWAP32(b) 的 结果 :0x78563412

/* 调用方式 */
uint16_t a = 0x1234;
uint16_t result_a = SWAP16(a);	// result_a = 0x3412;

uint32_t b = 0x12345678;
uint32_t result_b = SWAP32(b);	// result_b = 0x78563412;

异或实现方式

  异或这种方式,虽然可读性差,但相比算术的方法起码不会出错。

  算术的方法可能存在超出16位整数所能表示的范围,从而造成程序运行错误。函数传入的是指针,无返回值。

//算术的方式
void swap_a_b(uint8_t* a, uint8_t* b)
{
   
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}
//异或是位运算,特性是 (0, 0) = 0; (1, 0) = 1; (0, 1) = 1; (1, 1) = 0;
//举个例子:5 为 *a(0101), 12 为 *b(1100)
//*a = *a ^ *b;		//*a = 1001。右侧:(0101) ^ (1100)
//*b = *a ^ *b;		//*b = 0101。右侧:(1001) ^ (1100)
//*a = *a ^ *b;		//*a = 1100。右侧:(1001) ^ (0101)

void swap16(uint16_t* data)
{
   
    uint8_t* temp = (uint8_t*)data;

    p[0] ^= p[1];
    p[1] ^= p[0];
    p[0] ^= p[1];
} 

void a_swap32(uint32_t* data)
{
   
    uint8_t* temp = (uint8_t*)data;

    p[0] ^= p[3];
    p
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值