自制Linux DNS服务器:不移动void指针访问数据的高效C实现?
DNS数据包偏移访问16位整数的优化实现
你当前的写法不仅冗长,还存在未对齐访问的风险(当pos为奇数时,强制转换为uint16_t*会指向未对齐地址,在ARM等架构上可能触发崩溃或性能损耗)。以下是几种更高效、简洁且安全的实现方式:
1. 手动字节组合(推荐基础写法)
先将void* data转换为字节指针,直接通过偏移读取单个字节并组合成16位整数——DNS协议使用大端字节序,这种写法等价于ntohs,且完全避免未对齐问题:
const uint8_t* buf = (const uint8_t*)data; uint16_t val = ((uint16_t)buf[pos] << 8) | buf[pos + 1];
2. 封装为内联函数(兼顾简洁与安全)
把上述逻辑封装成内联函数,既简化调用,又避免宏可能带来的表达式重复计算副作用:
#include <stdint.h> #include <stddef.h> static inline uint16_t read_dns_u16(const void* data, size_t pos) { const uint8_t* buf = (const uint8_t*)data; return ((uint16_t)buf[pos] << 8) | buf[pos + 1]; } // 调用示例 uint16_t val = read_dns_u16(data, pos);
3. 封装为宏(极致简洁)
如果追求代码最短,也可以用宏实现,但注意如果pos是复杂表达式(比如pos++),会重复计算:
#define READ_DNS_U16(data, pos) \ (((uint16_t)*((const uint8_t*)data + pos) << 8) | \ *((const uint8_t*)data + pos + 1)) // 调用示例 uint16_t val = READ_DNS_U16(data, pos);
这些实现都比你原来的写法更高效:一方面消除了未对齐访问的性能损耗或崩溃风险,另一方面避免了多层强制转换的冗余操作,编译器也能更轻松地优化代码。
内容的提问来源于stack exchange,提问作者Dimitris
相关产品推荐
相关产品推荐

