c++ - 什么时候使用 __bswap_constant_XX 而不是 __bswap_XX?

标签 c++ c endianness

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

我正在使用 GCC 4.8

最佳答案

首先,您通常不应该使用带有双下划线的符号,因为它们是 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

关于c++ - 什么时候使用 __bswap_constant_XX 而不是 __bswap_XX?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55758281/

相关文章:

ada - 读取字节流记录

c++ - 读取以 bigendian 编写的文件

c++ - 返回 vector 中结构位置的索引

python - 如何使用 Python 从 24 位和小端字节序的文件中读取整数?

C++ - 读入以逗号分隔的文件行

c - 奇怪的 OpenCV 距离变换结果

c - 如何在不直接声明字符串的情况下将指针指向字符串

php - 如何使 ZEND_BEGIN_ARG_INFO_EX 控制传递给 PHP 扩展的参数数量?

c++ - 包装 C 或 C++ 库的优点和缺点是什么

c++ - 如何获取给定监视器上存在的所有窗口的 HWND?