Почему 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 принимает меры предосторожности, гарантируя, что перекрытие не обернется конечным результатом.

Другие вопросы по тегам