考虑一下我在this question中找到的此功能:
void to_bytes(uint64_t const& x, uint8_t* dest) {
dest[7] = uint8_t(x >> 8*7);
dest[6] = uint8_t(x >> 8*6);
dest[5] = uint8_t(x >> 8*5);
dest[4] = uint8_t(x >> 8*4);
dest[3] = uint8_t(x >> 8*3);
dest[2] = uint8_t(x >> 8*2);
dest[1] = uint8_t(x >> 8*1);
dest[0] = uint8_t(x >> 8*0);
}
由于x
和dest
可能指向相同的内存,因此不允许编译器将其优化为单个qword移动(每行可能会更改x
的值)。
到目前为止很好。
但是,如果您改为通过值传递x
,则该参数不再成立。
实际上,GCC可以按预期将其优化为一条简单的mov
指令:https://godbolt.org/z/iYj1or
但是,铛不会:https://godbolt.org/z/Hgg5z9
我假设,由于甚至无法保证x
根本不占用任何堆栈内存,因此任何试图使dest
指向x
的尝试都是之前调用该函数将导致未定义的行为,因此编译器可以假定这种情况永远不会发生。那意味着c在这里失去了一些机会。但是我不确定。有人可以澄清吗?
答案 0 :(得分:2)
您提供的代码过于复杂。您可以将其替换为:
void to_bytes(uint64_t x, uint8_t* dest) {
x = htole64(x);
std::memcpy(dest, &x, sizeof(x));
}
是的,它使用Linux-ism htole64()
,但是如果您在另一个平台上,则可以轻松地重新实现它。
在小端和大端平台上,Clang和GCC可以完美地优化这一点。