有人能告诉我__bswap_constant_XX
和__bswap_XX
有什么区别,什么时候比另一个更喜欢?
我正在使用GCC 4.8
答案 0 :(得分:1)
首先,通常不应该使用带有双下划线的符号,因为它们是reserved。
您正在谈论的符号不是编译器定义的,而是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