提问人: 提问时间:10/11/2023 更新时间:10/11/2023 访问量:106
编译时间字节序相关表达式?
Compile time endian dependent expressions?
问:
在实现 UDP BitTorrent 跟踪器协议时,我注意到最常见的数据包解析步骤是检查前 64 位是否是协议 ID ,用于请求连接,然后再回退到假设它是给定的连接 ID 之一。0x41727101980
我意识到连接 id 的字节序性在仅用作唯一位序列时并不重要,所以我有一个想法,根本不将其从网络字节顺序转换为主机,而是简单地按原样使用这些值,但只有一个问题,协议 ID 如所写的那样,与以大端序编码的数据包中的协议 ID 不匹配, 除非代码在大端机器上运行,否则无论如何我都必须一直在某个地方转换前 64 位。
我知道我可以在运行时转换一次值,但也许有一些技巧允许在 a 中表达这个值,以确保无论系统的字节序如何,它都将始终以 big endian 编码?0x41727101980
uint64_t
我真正想知道的是,是否等同于:
static uint64_t const PROTOCOL_ID = htobe64(0x41727101980);
在编译时是可能的。
答:
2赞
dbush
10/11/2023
#1
帧挑战:您实际上不想真正想要一个编译时字节序相关的表达式。你真的想要一个字节序列。
因此,请将您的协议 ID 定义为:
static const uint8_t PROTOCOL_ID[8] = {0x0,0x0,0x4,0x17,0x27,0x10,0x19,0x80};
然后用于将其与 UDP 缓冲区的开头进行比较。这比我怀疑您正在做的事情更安全,即将缓冲区的开头转换为 ,取消引用,并与另一个可能与严格的别名和对齐问题相冲突的缓冲区进行比较。memcmp
uint64_t *
uint64_t
评论
0赞
10/11/2023
我总是,这可选地导致,能够直接做就好了。我相信我的编译器会在大多数处理器上用简单的 bswap 指令替换 be64toh,因此需要调查指针大小或更小的大小,这可能没有区别,只是更晦涩的代码。我还知道有一个全局变量,我使用运行时 be64toh 在 main 中初始化,但这是另一个需要跟踪的疣。memcpy(&bits64, buf + offset, sizeof(bits64));
bits64 = be64toh(bits64);
bits64 == 0x41727101980
memcmp
评论
static uint8_t const PROTOCOL_ID[8] = {0x00, 0x00, 0x04, 0x17, 0x27, 0x10, 0x19, 0x80};
htobe64