2010-08-26 3 views
5

Может ли кто-нибудь помочь мне понять, как memmove реализован в C. У меня есть только одно специальное условие?memmove реализация в C

if((src<dst)&&((src+sz) > dst)) 

copy from the back 

Также зависит ли это от того, как стек растет?

+0

Если 'src',' dst' и 'sz' - все положительные значения, условие является неудовлетворительным. Если 'src> dst', добавление к нему положительного' sz' не будет делать этого меньше. – Edmund

+0

@ Edmund I исправлено – brett

ответ

28

Математически, вам не нужно беспокоиться о том, что они перекрываются вообще. Если src меньше dst, просто скопируйте его с конца. Если src больше dst, просто скопируйте его с самого начала.

Если и dst равны, сразу же выйдите.

Это потому, что ваши дела являются одним из:

1) <-----s----->    start at end of s 
       <-----d-----> 

2) <-----s----->    start at end of s 
      <-----d-----> 

3) <-----s----->    no action 
    <-----d-----> 

4)   <-----s----->  start at beginning of s 
    <-----d-----> 

5)    <-----s-----> start at beginning of s 
    <-----d-----> 

Даже если нет перекрытия, что все равно будет работать нормально, и упростить условия.

Если у вас есть более эффективный способ копирования вперед, чем назад, то да, вы должны проверить наложение, чтобы убедиться, что используете более эффективный метод, если это возможно. Другими словами, измените вариант 1 выше, чтобы скопировать с самого начала.

+1

Обратите внимание, что есть другое скрытое предположение, которое заключается в том, что вы копируете только байт за раз. – caf

+2

Ну, независимо от того, копируете ли вы байт за раз или квадрат или какое-то массивное значение гиперссылки SSE9 1024-бит, теория остается прежней.Вы должны убедиться, что вы не копируете _into_ область перекрытия, которую вы еще не скопировали _out__. Все варианты N-is-wide-than-char представляют собой несколько более сложное обнаружение перекрытия (и окончательной передачи) в случае, когда он не является прямым кратным значению N. – paxdiablo

+0

@caf: Если 'src' и 'dest' имеют одинаковое выравнивание по отношению к более крупному типу, который вы могли бы скопировать, но вам никогда не придется беспокоиться о том, что вы клонируете область, которую вы еще не скопировали, поскольку позиции всегда будут отличаться по крайней мере на таком размере. Если они не разделяют одно и то же выравнивание, вы все равно застреваете в качестве байтов ... если вы не хотите использовать некоторые неприятные x86 unaligned io ... –

1

Зависит от компилятора. Хорошие компиляторы будут использовать хорошую оптимизацию, зависящую от набора инструкций целевого процессора и ширины шины.

+0

Я верю, что это должно идти в комментарий вместо отдельного ответа – YeenFei

5

memmove может быть преобразовано в memcpy, если две области памяти не перекрываются. Очевидно, что memcpy чрезвычайно оптимизирован для большинства систем (один из используемых мной использует почти каждый трюк в книге из развернутых циклов в SSE-операции, где поддерживается максимальная пропускная способность).

Если две области памяти накладываются друг на друга, для целей и целей область, подлежащая копированию, перемещается во временный буфер, а временный буфер копируется (все с memcpy, скорее всего) обратно поверх исходного буфера. Вы не можете работать с самого начала или работать со спины с перекрывающимся регионом, потому что вы всегда будете иметь по крайней мере некоторые данные, которые будут повреждены в процессе.

Это было давно, так как я смотрел код libc, поэтому может быть оптимизация для memmove и перекрывающихся областей, о которых я еще не думал.

memmove не зависит от того, как стек растет вообще - он просто копирует одну область памяти в другое место - точно так же, как memcpy, за исключением того, что он обрабатывает перекрывающиеся области, а memcpy - нет.

EDIT: На самом деле, подумайте об этом еще ... Работа со спины может работать, если вы перейдете от правого «источника» (так сказать), в зависимости от самого перемещения (например, это источник < dest или не?). Вы можете прочитать реализацию newlib here, и tt достаточно хорошо прокомментирован.

+0

Я бы хотел, чтобы вы копировали во временный буфер, когда 'n' является' SIZE_MAX >> 1' ... –

Смежные вопросы