编译时间字节序相关表达式?

Compile time endian dependent expressions?

提问人: 提问时间:10/11/2023 更新时间:10/11/2023 访问量:106

问:

在实现 UDP BitTorrent 跟踪器协议时,我注意到最常见的数据包解析步骤是检查前 64 位是否是协议 ID ,用于请求连接,然后再回退到假设它是给定的连接 ID 之一。0x41727101980

我意识到连接 id 的字节序性在仅用作唯一位序列时并不重要,所以我有一个想法,根本不将其从网络字节顺序转换为主机,而是简单地按原样使用这些值,但只有一个问题,协议 ID 如所写的那样,与以大端序编码的数据包中的协议 ID 不匹配, 除非代码在大端机器上运行,否则无论如何我都必须一直在某个地方转换前 64 位。

我知道我可以在运行时转换一次值,但也许有一些技巧允许在 a 中表达这个值,以确保无论系统的字节序如何,它都将始终以 big endian 编码?0x41727101980uint64_t

我真正想知道的是,是否等同于:

static uint64_t const PROTOCOL_ID = htobe64(0x41727101980);

在编译时是可能的。

C 常量字节 序编译

评论

0赞 BurnsBA 10/11/2023
这回答了你的问题吗?在编译时确定字节序
1赞 BurnsBA 10/11/2023
您的问题正文和标题都要求在编译时确定独立性,如果这不是您要问的,则需要更新问题。
1赞 10/11/2023
@BurnsBA我的问题和它的标题都没有“在编译时确定字节序”,但我甚至写了一行代码来说明这一点。
1赞 Ry- 10/11/2023
不认为适合你?顺便说一句,为什么在编译时需要它?因为如果它是为了性能,请注意编译器已经优化到常量。static uint8_t const PROTOCOL_ID[8] = {0x00, 0x00, 0x04, 0x17, 0x27, 0x10, 0x19, 0x80};htobe64
1赞 n. m. could be an AI 10/11/2023
您的问题严格等同于在编译时确定字节序。如果可以在编译时确定字节序,则可以在编译时创建具有给定字节表示形式的整数;如果可以在编译时创建具有给定字节表示形式的整数,则可以在编译时确定字节序。

答:

2赞 dbush 10/11/2023 #1

帧挑战:您实际上不想真正想要一个编译时字节序相关的表达式。你真的想要一个字节序列。

因此,请将您的协议 ID 定义为:

static const uint8_t PROTOCOL_ID[8] = {0x0,0x0,0x4,0x17,0x27,0x10,0x19,0x80};

然后用于将其与 UDP 缓冲区的开头进行比较。这比我怀疑您正在做的事情更安全,即将缓冲区的开头转换为 ,取消引用,并与另一个可能与严格的别名和对齐问题相冲突的缓冲区进行比较。memcmpuint64_t *uint64_t

评论

0赞 10/11/2023
我总是,这可选地导致,能够直接做就好了。我相信我的编译器会在大多数处理器上用简单的 bswap 指令替换 be64toh,因此需要调查指针大小或更小的大小,这可能没有区别,只是更晦涩的代码。我还知道有一个全局变量,我使用运行时 be64toh 在 main 中初始化,但这是另一个需要跟踪的疣。memcpy(&bits64, buf + offset, sizeof(bits64));bits64 = be64toh(bits64);bits64 == 0x41727101980memcmp