何时使用__bswap_constant_XX而不是__bswap_XX?

问题描述 投票:1回答:1

任何人都可以告诉我__bswap_constant_XX__bswap_XX之间的区别是什么时候更喜欢一个而不是另一个?

我正在使用GCC 4.8

c++ c endianness
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.