【发布时间】:2019-04-28 16:10:35
【问题描述】:
为了避免违反严格的别名规则,我在我的代码中的几个地方引入了memcpy,希望它是一个空操作。以下示例在 gcc 和 clang 上生成对 memcpy(或等效项)的调用。具体来说,fool<40> 总是这样做,而 foo 在 gcc 上运行但不是 clang,fool<2> 在 clang 但不是 gcc 上运行。何时/如何优化?
uint64_t bar(const uint16_t *buf) {
uint64_t num[2];
memcpy(&num, buf, 16);
return num[0] + num[1];
}
uint64_t foo(const uint16_t *buf) {
uint64_t num[3];
memcpy(&num, buf, sizeof(num));
return num[0] + num[1];
}
template <int SZ>
uint64_t fool(const uint16_t *buf) {
uint64_t num[SZ];
memcpy(&num, buf, sizeof(num));
uint64_t ret = 0;
for (int i = 0; i < SZ; ++i)
ret += num[i];
return ret;
}
template uint64_t fool<2>(const uint16_t*);
template uint64_t fool<40>(const uint16_t*);
【问题讨论】:
-
你误解了一些东西。
<2>不会用 clang 或 gcc 调用memcpy。<40>调用memcpy仅使用 clang。如果您只为一个uint64_t应用memcpy,则可以轻松删除它(我的意思是,将memcpy放入for 循环中)。 -
@geza 他们正在制作一个“等效”(这无疑是不精确的......)。即有一个对应的
mov。 -
这很可能意味着 memcpy 被内联并且(不幸的是)没有别的。因此,虽然没有实际调用 memcpy 函数,但仍在制作副本,而不是将给定内存的预期效果简单地解释为目标类型的对象。