> 文章列表 > __builtin_xxx指令学习【5】__builtin_bswap16/32/64

__builtin_xxx指令学习【5】__builtin_bswap16/32/64

__builtin_xxx指令学习【5】__builtin_bswap16/32/64

__builtin_bswap16/32/64是GCC和Clang编译器提供的内置函数,用于交换一个整数的字节顺序。其中,__builtin_bswap16用于交换一个16位整数的字节顺序,__builtin_bswap32用于交换一个32位整数的字节顺序,__builtin_bswap64用于交换一个64位整数的字节顺序。这些函数的使用背景是在一些网络编程和底层编程中,需要对字节序进行处理和转换,而交换字节顺序是一个常见的操作。

__builtin_bswap16/32/64的内部原理是使用CPU的指令集来实现交换。具体来说,当CPU支持BSWAP指令时,__builtin_bswap16/32/64会使用BSWAP指令来实现交换;否则,__builtin_bswap16/32/64会使用一些位运算技巧来实现交换。在实现中,__builtin_bswap16/32/64会根据不同的CPU架构和编译器选项来选择最优的实现方式,从而提高交换效率。

__builtin_bswap16/32/64的弊端是可能会导致代码的可移植性问题。由于__builtin_bswap16/32/64是GCC和Clang编译器提供的内置函数,因此在使用__builtin_bswap16/32/64时,需要确保代码的可移植性,并且需要在代码中添加条件编译来处理不支持BSWAP指令的CPU。另外,由于__builtin_bswap16/32/64的实现依赖于CPU架构和编译器选项,因此在不同的平台和编译器下,__builtin_bswap16/32/64的性能可能会有差异。

下面给出一个demo,这里为了平台兼容性我们也实现了不支持__builtin_bswap的对应的函数。

在这个代码中,我们首先使用defined(__GNUC__) || defined(__clang__)来判断当前编译器是否是GCC或Clang。如果是,我们再使用defined(__x86_64__) || defined(__i386__)来判断当前CPU是否是x86或x86-64架构。如果是,我们就定义BSWAP_SUPPORTED宏,表示当前CPU支持BSWAP指令。

接下来,我们使用#ifdef BSWAP_SUPPORTED来判断当前CPU是否支持BSWAP指令。

#include <iostream>
#include <chrono>
#include <cstdint>#if defined(__GNUC__) || defined(__clang__)#if defined(__x86_64__) || defined(__i386__)#define BSWAP_SUPPORTED#endif
#endif#ifdef BSWAP_SUPPORTED#define bswap16 __builtin_bswap16#define bswap32 __builtin_bswap32#define bswap64 __builtin_bswap64
#elsetemplate<typename T>T bswap(T value) {static_assert(std::is_integral<T>::value, "bswap only works with integral types");uint8_t* ptr = reinterpret_cast<uint8_t*>(&value);for (size_t i = 0, j = sizeof(T) - 1; i < j; ++i, --j) {std::swap(ptr[i], ptr[j]);}return value;}template<typename T>T bswap16(T value) {static_assert(std::is_integral<T>::value, "bswap16 only works with integral types");uint16_t result = bswap(static_cast<uint16_t>(value));return static_cast<T>(result);}template<typename T>T bswap32(T value) {static_assert(std::is_integral<T>::value, "bswap32 only works with integral types");uint32_t result = bswap(static_cast<uint32_t>(value));return static_cast<T>(result);}template<typename T>T bswap64(T value) {static_assert(std::is_integral<T>::value, "bswap64 only works with integral types");uint64_t result = bswap(static_cast<uint64_t>(value));return static_cast<T>(result);}
#endifint main() {uint16_t a = 0x1234;uint32_t b = 0x12345678;uint64_t c = 0x123456789abcdef0;std::cout << std::hex << bswap16(a) << "\\n";std::cout << std::hex << bswap32(b) << "\\n";std::cout << std::hex << bswap64(c) << "\\n";return 0;
}

打印

3412
78563412
f0debc9a78563412