Рассмотрим эту функцию, которую я нашел в этот вопрос :
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
Однако Clang не делает: https://godbolt.org/z/Hgg5z9
Я предполагаю, что, поскольку даже не гарантируется, что x
вообще занимает какую-либо память стека, любая попытка dest
указать на x
до вызываемой функции будет приводит к неопределенному поведению, и, таким образом, компилятор может предположить, что этого просто никогда не произойдет. Это означало бы, что у кланга здесь не хватает возможности. Но я не уверен. Может кто-нибудь уточнить?