在uint8_t [8]&之间安全转换uint64_t通过演员?

时间:2015-03-22 13:41:38

标签: c optimization casting memcpy memory-alignment

我目前的做法(我更愿意摆脱memcpy电话):

uint64_t integer;
uint8_t string[8];
...
memcpy(&integer, &string, 8); //or swap the parameters

假设integer数组长度始终为8的倍数(总分配为64位)是否可以在给定编译器填充/对齐问题的情况下进行直接转换?

1 个答案:

答案 0 :(得分:4)

如果您正在努力优化,则无需避免或替换memcpy()来电。每个现代优化编译器都不会发出调用并生成等效的汇编代码。较新的GCC和Clang版本甚至在没有给出优化相关选项时也会这样做。顺便说一句,可以使用-fno-builtin禁用该行为。

您可以使用C++ Compiler Explorer(当然还有本地-S)自行验证:

#include <string.h>
#include <stdint.h>

uint64_t
u8tou64(uint8_t const u8[static 8]){
  uint64_t u64;
  memcpy(&u64, u8, sizeof u64);
  return u64;
}

例如,针对x86_64的GCC 4.8.1产生:

u8tou64:
    push    rbp
    mov rbp, rsp
    mov QWORD PTR [rbp-24], rdi
    mov rax, QWORD PTR [rbp-24]
    mov rax, QWORD PTR [rax]
    mov QWORD PTR [rbp-8], rax
    mov rax, QWORD PTR [rbp-8]
    pop rbp
    ret

使用-O3

u8tou64:
    mov rax, QWORD PTR [rdi]
    ret
John Regehr的

This blog post得出了相同的结论(c5()调用memcpy()):

  

在我看来,c5是最容易理解的代码   一批功能,因为它不会做凌乱的转移也   它完全,完全,显然没有可能的并发症   来自工会的混乱规则和严格的混淆。它   几年前当我成为打字的时候,我成了我的首选成语   发现编译器可以透过memcpy看到并生成   正确的代码。

使用联合或按位运算等替代方法可能不会产生最佳(且看起来不错的)代码,或者无法在ISO C90或C ++中使用(这也包括GCC&#39; __may_alias__属性这在评论部分提到。)