给定一个包含我需要解析的 32 位小端字段的二进制文件,我想编写能够正确编译的解析代码,而与执行该代码的机器的端序无关。目前我在用
uint32_t fromLittleEndian(const char* data){
return uint32_t(data[3]) << (CHAR_BIT*3) |
uint32_t(data[2]) << (CHAR_BIT*2) |
uint32_t(data[1]) << CHAR_BIT |
data[0];
}
然而,这会产生非最佳装配。在我的机器上 g++ -O3 -S
产生:
_Z16fromLittleEndianPKc:
.LFB4:
.cfi_startproc
movsbl 3(%rdi), %eax
sall $24, %eax
movl %eax, %edx
movsbl 2(%rdi), %eax
sall $16, %eax
orl %edx, %eax
movsbl (%rdi), %edx
orl %edx, %eax
movsbl 1(%rdi), %edx
sall $8, %edx
orl %edx, %eax
ret
.cfi_endproc
为什么会这样?我怎样才能说服它在小端机器上编译时生成最佳代码:
_Z17fromLittleEndian2PKc:
.LFB5:
.cfi_startproc
movl (%rdi), %eax
ret
.cfi_endproc
这是我通过编译得到的:
uint32_t fromLittleEndian2(const char* data){
return *reinterpret_cast<const uint32_t*>(data);
}
因为我知道我的机器是小端,所以我知道上面的汇编是最优的,但是如果在大端机器上编译它会失败。它还违反了严格的别名规则,因此如果内联它甚至在小端机器上也可能产生 UB。 如果可能的话是否有一个有效的代码将被编译成最佳汇编?
因为我希望我的函数内联很多,所以任何类型的运行时字节序检测都是不可能的。编写最佳 C/C++ 代码的唯一替代方法是使用编译时字节序检测,如果目标字节序,则使用 template
或 #define
回退到低效代码不是小端。然而,这似乎很难便携地完成。
最佳答案
简短的回答 - 使用 htonl - 它会被 wazzoo 优化
关于c++ - c/c++中endian的最佳和可移植转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36657895/