问题描述
上一篇中遇到一个问题:小端模式的必然性(先低字节后高字节) 和 自定义协议的不可更改性,导致无法衔接。而本来可以避免的(定义协议的时候考虑到),否则就会导致代码的可读性下降,多上一大堆语句,可维护性下降,(报文解包和打包时都需要进行高低字节翻转)。
既然遇到问题了,那就该反馈问题,实在不行就解决/消化问题:解决十六位数 和 三十位数的 高低位交换。
本来还有点儿发愁该怎么实现好,结果一下子找到了四五种解决方式,着实有点儿出乎意料。
主要参考这篇文章:多字节变量的高低字节交换 和 蓝牙工程中的一些代码。
宏定义方式
通过移位方式实现高低位交换。
#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 =