Может ли кто-нибудь помочь мне понять, как memmove реализован в C. У меня есть только одно особое условие, верно?
if((src<dst)&&((src+sz) > dst))
copy from the back
Также это зависит от того, как растет стек?
Может ли кто-нибудь помочь мне понять, как memmove реализован в C. У меня есть только одно особое условие, верно?
if((src<dst)&&((src+sz) > dst))
copy from the back
Также это зависит от того, как растет стек?
Математически вам не нужно беспокоиться о том, перекрываются ли они вообще. Если src
меньше dst
, просто скопируйте с конца. Если src
больше, чем dst
, просто скопируйте с самого начала.
Если src
и 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 выше, чтобы скопировать с самого начала.
src
и dest
имеют одинаковое выравнивание по отношению к более крупному типу, который вы можете скопировать, вам никогда не придется беспокоиться о затирании области, которую вы еще не скопировали, поскольку позиции всегда будут отличаться как минимум на этот размер. Если они не имеют одинакового выравнивания, вы все равно застряли при копировании как байты... если только вы не хотите использовать какой-то неприятный невыровненный x86 io...
- person R.. GitHub STOP HELPING ICE; 04.09.2010
memmove можно превратить в memcpy, если две области памяти не т перекрываются. Очевидно, что memcpy чрезвычайно оптимизирован для большинства систем (одна из тех, которые я использую, использует почти все приемы в книге, от развернутых циклов до операций SSE, где поддерживается максимальная пропускная способность).
Если две области памяти перекрываются, для всех целей копируемая область перемещается во временный буфер, а временный буфер копируется (скорее всего, все с помощью memcpy) обратно поверх исходного буфера. Вы не можете работать с самого начала или с конца с перекрывающейся областью, потому что в процессе всегда будут повреждены хотя бы некоторые данные.
При этом я давно не смотрел на код libc, поэтому может быть оптимизация для memmove и перекрывающихся областей, о которой я еще не думал.
memmove вообще не зависит от того, как растет стек — он просто копирует одну область памяти в другую — точно так же, как memcpy, за исключением того, что он обрабатывает перекрывающиеся области, а memcpy — нет.
РЕДАКТИРОВАТЬ: На самом деле, подумав об этом еще немного... Работа со спины может работать, если вы идете из правильного "источника" (так сказать), в зависимости от самого движения (например, является ли источник ‹ местом назначения или нет?). Вы можете прочитать реализацию newlib здесь, и она также довольно хорошо прокомментирована.
Зависит от компилятора. Хорошие компиляторы будут использовать хорошие оптимизации в зависимости от набора инструкций целевого процессора и ширины шины.
src
,dst
иsz
все положительные значения, условие невыполнимо. Еслиsrc > dst
, добавление к нему положительногоsz
не сделает его меньше. - person Edmund   schedule 26.08.2010