何时使用 __bswap_constant_XX 而不是__bswap_XX?

When to use __bswap_constant_XX instead of __bswap_XX?

本文关键字:XX bswap constant 何时使      更新时间:2023-10-16

谁能告诉我__bswap_constant_XX__bswap_XX之间有什么区别,以及什么时候更喜欢一个而不是另一个?

我正在使用 GCC 4.8

首先,您通常不应使用带有双下划线的符号,因为这些符号是保留的。

您正在谈论的符号不是编译器定义的,而是 C 库的一部分。bswap_XX宏可以使用编译器内部甚至内联汇编来使编译器生成特定于 CPU 的指令,从而使结果在编译时未知。

相反,__bswap_constant_XX应该使用简单的 C 表达式计算值,如果输入是编译时常量,则使值编译时常量。

此类宏可以定义为:

#define __bswap_constant_16(x)                                  
((__uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
#define __bswap_constant_32(x)                                  
((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) |   
(((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))

这个想法是,当你需要编译时值时,例如在定义枚举值时,你应该使用__bswap_constant_XX

enum myenum {
MYVALUE = __bswap_constant_16(0x1234)
};

bswap_XX应该在所有其他情况下使用。

请注意,现代编译器能够识别简单的字节交换模式并生成适当的指令,因此在实践中,这在大多数情况下不会产生影响。

例如,对于这两个函数:

uint16_t bswap16(uint16_t x)
{
return __bswap_constant_16(x);
}
uint32_t bswap32(uint32_t x)
{
return __bswap_constant_32(x);
}

GCC 4.8.1 生成:

bswap16:
mov     eax, edi
rol     ax, 8
ret
bswap32:
mov     eax, edi
bswap   eax
ret