- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
void * c_memmove(void *dest, void *src, size_t n)
{
void *ret = dest;
if (n)
{
*(__int8 **)&dest += n;
*(__int8 **)&src += n;
switch (int x = n % 4)
{
do
{
if (!!'true')
{
case 0:
*--*(__int32 **)&dest = *--*(__int32 **)&src;
n -= 4;
}
else
{
case 3:
*--*(__int8 **)&dest = *--*(__int8 **)&src;
case 2:
*--*(__int8 **)&dest = *--*(__int8 **)&src;
case 1:
*--*(__int8 **)&dest = *--*(__int8 **)&src;
n -= x;
}
} while (n);
}
}
return ret;
}
это что за хэш?
чем отличается от
(_int8*)dest
?
для некоторых это критично
код является тонкой вариацией на тему http://govnokod.ru/8397, но при этом умудряется выполнять почти ровно то, что задумано, т.е. тут по делу все эти несчастные if и while
даже 'true' ок
да, *--* это скорее ради гламура
какие проблемы я вижу в этом коде:
1) это memcpy, а не memmove
2) аргумент src должен быть void const *
3) - самое главное - похвальная попытка копировать блоками по 4 байта, которая однако не приведет к желаемому результату, если либо src, либо dest не будут на момент входа в функцию сами выровнены по границе слова
я даже подозреваю кто это запостил
потому что фэйк.
почти все современные компилеры способны сами съоптимизировать эти операции.
а те у кого нету человеческого или современного компилера, киздят код из BSD.
те, у кого нет человеческого компилера, пользуются старым добрым побайтным memcpy или memmove, потому что платформа может показать кукиш при невыровненном обращении руками (и потом кури логи при загрузке embedded ОС), либо соптимизировать это таким образом, что побайтно быстрее (иначе, например, берет исходное слово, заменяет в нем байт, кладет обратно)
и да, поделишься сорцами memcpy.c из бсд? а то гугл мне находит в основном только версию "This is designed to be small, not fast.", делающую по-миссионерски
если компилить как .c код то кастинг дает lvalue
а если как .cpp то rvalue и вываливается с такой ошибкой
error C2105: '--' needs l-value
поэтому
*(__int8 **)&dest
чем отличается от
(_int8*)dest
?
второй вариант просто не скомпилируется в .cpp режиме
а когда мы берем адрес указателя и разыменовываем то получаем
lvalue и в .c и в .cpp режиме потом делаем декремент и еще одно
разыменование для записи копируемых данных так что нет не для гламура
блоки перекрывающиеся можно было копировать а memcpy
копирует сначала так что по поведению это чистый memmove
если dest < src, то копировать с головы, иначе - с хвоста
memcpy нет, и линус от этого получает неимоверный батхерт, он даже предлагал сделать memcpy синонимом memmove
That said - why the heck would you ever do memcpy() backwards? Things like automatic prefetchers usually work better for the "natural" patterns, so a backwards memcpy is generally a bad thing to do unless you have some active reason for it, like doing a memmove()
но на интелах это решается установкой/сбросом флага
что в ЧПУ, что в ДМА
А вот разработчики Intel и AMD пошли дальше и написали код, делающий memcpy/memmove сначала через mmx, потом через xmm-регистры. И судя по тестам он намного быстрее на больших объёмах памяти. Вот так вот.