Tim*_*mmm 12 c++ clang endianness
如果要转换uint64_t为uint8_t[8](小尾数)。在小端架构上,您可以执行ug reinterpret_cast<>或memcpy(),例如:
void from_memcpy(const std::uint64_t &x, uint8_t* bytes) {
std::memcpy(bytes, &x, sizeof(x));
}
Run Code Online (Sandbox Code Playgroud)
这将产生有效的组装:
mov rax, qword ptr [rdi]
mov qword ptr [rsi], rax
ret
Run Code Online (Sandbox Code Playgroud)
但是,它不是便携式的。在一点字节序的机器上它将具有不同的行为。
要转换uint8_t[8]成uint64_t一个很好的解决方案-只需执行以下操作:
mov rax, qword ptr [rdi]
mov qword ptr [rsi], rax
ret
Run Code Online (Sandbox Code Playgroud)
这看起来效率低下,但实际上使用Clang时,-O2它会生成与以前完全相同的程序集,如果在大型字节序计算机上进行编译,它将足够聪明以使用本机字节交换指令。例如此代码:
void to(const std::uint8_t* bytes, std::uint64_t &x) {
x = (std::uint64_t(bytes[0]) << 8*0) |
(std::uint64_t(bytes[1]) << 8*1) |
(std::uint64_t(bytes[2]) << 8*2) |
(std::uint64_t(bytes[3]) << 8*3) |
(std::uint64_t(bytes[4]) << 8*4) |
(std::uint64_t(bytes[5]) << 8*5) |
(std::uint64_t(bytes[6]) << 8*6) |
(std::uint64_t(bytes[7]) << 8*7);
}
Run Code Online (Sandbox Code Playgroud)
编译为:
mov rax, qword ptr [rdi]
bswap rax
mov qword ptr [rsi], rax
ret
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否存在用于反向转换的等效可靠优化结构?我已经尝试过了,但是天真地编译了它:
void to(const std::uint8_t* bytes, std::uint64_t &x) {
x = (std::uint64_t(bytes[7]) << 8*0) |
(std::uint64_t(bytes[6]) << 8*1) |
(std::uint64_t(bytes[5]) << 8*2) |
(std::uint64_t(bytes[4]) << 8*3) |
(std::uint64_t(bytes[3]) << 8*4) |
(std::uint64_t(bytes[2]) << 8*5) |
(std::uint64_t(bytes[1]) << 8*6) |
(std::uint64_t(bytes[0]) << 8*7);
}
Run Code Online (Sandbox Code Playgroud)
编辑:经过一些试验,只要您使用,就可以使用GCC 8.1及更高版本对代码进行最佳编译uint8_t* __restrict__ bytes。但是我仍然没有找到Clang会优化的形式。
如果返回一个值呢?易于推理且组装规模小:
#include <cstdint>
#include <array>
auto to_bytes(std::uint64_t x)
{
std::array<std::uint8_t, 8> b;
b[0] = x >> 8*0;
b[1] = x >> 8*1;
b[2] = x >> 8*2;
b[3] = x >> 8*3;
b[4] = x >> 8*4;
b[5] = x >> 8*5;
b[6] = x >> 8*6;
b[7] = x >> 8*7;
return b;
}
Run Code Online (Sandbox Code Playgroud)
和大端:
#include <stdint.h>
struct mybytearray
{
uint8_t bytes[8];
};
auto to_bytes(uint64_t x)
{
mybytearray b;
b.bytes[0] = x >> 8*0;
b.bytes[1] = x >> 8*1;
b.bytes[2] = x >> 8*2;
b.bytes[3] = x >> 8*3;
b.bytes[4] = x >> 8*4;
b.bytes[5] = x >> 8*5;
b.bytes[6] = x >> 8*6;
b.bytes[7] = x >> 8*7;
return b;
}
Run Code Online (Sandbox Code Playgroud)
(std::array 不适用于 -target aarch64_be?)
| 归档时间: |
|
| 查看次数: |
314 次 |
| 最近记录: |