Почему Linux memmove() реализован таким, какой он есть?
Из справочной страницы Linux для memmove(3)
Функция memmove() копирует n байтов из области памяти src в область памяти dest. Области памяти могут перекрываться: копирование происходит так, как будто байты в src сначала копируются во временный массив, который не перекрывает src или dest, а затем байты копируются из временного массива в dest.
Вместо того, чтобы выделять временный массив и дважды копировать значения, мы могли бы просто сделать следующее:
void *my_memmove(void *dest, const void *src, size_t n) {
signed char operation;
size_t end;
size_t current;
if(dest != src) {
if(dest < src) {
operation = 1;
current = 0;
end = n;
} else {
operation = -1;
current = n - 1;
end = -1;
}
for( ; current != end; current += operation) {
*(((unsigned char*)dest) + current) = *(((unsigned char*)src) + current);
}
}
return dest;
}
В этой реализации мы просто берем на себя позицию, с которой начинаем копировать.
Есть ли недостаток в моей реализации?
Примечание: я не буду использовать мою реализацию. Мне просто интересно.
1 ответ
Вы можете посмотреть исходный код memmove здесь, здесь, здесь и здесь.
Что вы заметите, так это то, что они на самом деле не создают временный массив. Страницы руководства написаны, чтобы помочь вам понять, что он делает логически, а не на самом деле. Следовательно, они говорят "как будто".
На самом деле memmove() копирует байты из src
в dest
и копирует вперед, если dest < src
(что по сути то же самое, что и memcpy), и наоборот.
Разница между memcpy
а также memmove
в том, что memcpy
слепо копирует вперед - вот почему dest
а также src
не должно пересекаться Но memmove
принимает меры предосторожности, гарантируя, что перекрытие не обернется конечным результатом.