Давайте немного подробнее посмотрим на memcpy
и, пока мы это делаем, на нотацию "большого О" или Ландау.
Во-первых, биг-о. Как я уже говорил в другом месте, стоит запомнить определение большого O, которое заключается в том, что некоторая функция g (n) называется O (f (n)) , когда существует константа k , для которой g (n) & le; кф (п) . То, что делает константа, позволяет вам игнорировать мелкие детали в пользу важной части. Как все отметили, memcpy
из n байтов будет O (n) в большинстве любой обычной архитектуры, потому что независимо от того, что вы должны переместить эти n байты, один кусок за раз. Итак, первая наивная реализация memcpy
в C может быть написана
unsigned char *
memcpy(unsigned char * s1, unsigned char * s2, long size){
long ix;
for(ix=0; ix < size; ix++)
s1[ix] = s2[ix];
return s1;
}
Это на самом деле O (n) , и это может заставить вас задуматься, почему мы вообще беспокоимся о рутинной библиотеке. однако, функция libc заключается в том, что они являются местом, где пишутся специфичные для платформы утилиты; если вы хотите оптимизировать архитектуру, это одно из мест, где вы можете это сделать. Итак, в зависимости от архитектуры , возможны более эффективные варианты реализации; например, в архитектуре IBM 360 есть инструкция MOVL
, которая перемещает данные большими кусками, используя очень высоко оптимизированный микрокод. Таким образом, вместо этого цикла реализация memcpy 360 вместо этого может выглядеть примерно так:
LR 3,S1 LOAD S1 ADDR in Register 3
LR 4,S2
MOVL 3,4,SIZE
(Между прочим, нет никаких гарантий, что это точно правильный код 360, но он послужит для иллюстрации.) Эта реализация выглядит как вместо того, чтобы n обходить цикл как код C сделал, он просто выполняет 3 инструкции.
Что на самом деле происходит, так это то, что он выполняет O (n) микро инструкции под крышками. То, что отличается между ними, является константой k ; потому что микрокод намного быстрее, и поскольку в инструкциях всего три шага декодирования, он значительно быстрее, чем наивная версия, но все равно O (n) - это просто константа меньше.
И именно поэтому вы можете эффективно использовать memcpy
- он не асимптотически быстрее, но реализация настолько быстра, насколько кто-то может сделать это на этой конкретной архитектуре .