/* ==================== 小端 int16 解析 ==================== */
static inline int16_t _i16le(const uint8_t *b)
{
return (int16_t)((uint16_t)b[1] << 8 | b[0]);
}
小端 int16 解析函数详解
我来给你逐行、逐位讲清楚这段代码的作用、原理和细节,你一看就懂。
代码功能总结
这是一个内联函数,作用是:
从一段小端格式的字节数组中,解析出一个 16 位有符号整数(int16_t)。
逐行拆解
/* ==================== 小端 int16 解析 ==================== */
// static inline:静态内联函数,编译时直接展开,无函数调用开销
static inline int16_t _i16le(const uint8_t *b)
{
// 核心:小端字节组合 → 16位有符号整数
return (int16_t)((uint16_t)b[1] << 8 | b[0]);
}
1. 函数参数
const uint8_t *b:指向连续2个字节的指针(uint8_t = 无符号8位/1字节)- 要求:
b必须有效,且至少有 2 个字节可读
2. 核心表达式解析
(uint16_t)b[1] << 8 | b[0]
我们一步一步算:
b[0]:低字节(小端存储的第一个字节)b[1]:高字节(小端存储的第二个字节)b[1] << 8:
把高字节左移 8 位,放到 16 位数的高 8 位| b[0]:
按位或,把低字节放到 16 位数的低 8 位(uint16_t)强转:
防止移位时溢出/符号干扰,先按无符号拼接
小端存储是什么?(关键)
- 小端(Little-Endian):低字节存低地址,高字节存高地址
- int16 由 2 字节组成:
高8位 + 低8位 - 内存里的顺序是:
地址: [0] [1] 内容: 低字节 高字节
所以解析时必须:
高字节 << 8 | 低字节
举个例子(最直观)
假设内存字节是:
uint8_t bytes[] = {0x34, 0x12}; // 小端存储
执行:
_i16le(bytes);
计算过程:
b[0] = 0x34(低字节)b[1] = 0x12(高字节)0x12 << 8 = 0x12000x1200 | 0x34 = 0x1234- 强转 int16_t → 结果 = 0x1234(十进制 4660)
为什么要这么写?
- 网络/串口/文件常用小端存储
- 跨平台解析二进制数据必须手动拼字节
static inline让函数零开销,性能极高- 先转
uint16_t再拼,避免符号位干扰
安全注意事项
- 传入的指针
b必须至少有 2 个有效字节 - 不能传 NULL
- 适用于所有支持 C99 及以上的编译器(ARM、x86、单片机都能用)
总结
- 功能:小端 2 字节 → int16 有符号整数
- 公式:
(高字节 << 8) | 低字节 - 优点:高效、通用、无平台依赖
- 用途:解析协议、文件、串口数据
浙公网安备 33010602011771号