Страницы

Поиск по вопросам

вторник, 26 марта 2019 г.

Что делают указатели в приведенном методе?

Пример:
// Copies count bytes from src to dst. The source and destination // blocks are permitted to overlap. public static void Copy(void* src, void* dst, int count) { byte* ps = (byte*)src; byte* pd = (byte*)dst; if (ps > pd) { for (; count != 0; count--) *pd++ = *ps++; // Тут } else if (ps < pd) { for (ps += count, pd += count; count != 0; count--) *--pd = *--ps; // И тут } }
Для меня понятно что именно делает данный метод. Для меня непонятно шаманство с указателями. Почему например в else if используется префикс, а в if постфикс? Можете разъяснить подробно?


Ответ

Все дело в инварианте цикла.
Когда идет побайтовое копирование "вперед" - указатели указывают на первый байт еще не обработанной области памяти:
----dddddddd---- ----ssssssss---- ^ ^ | | pd ps
Поэтому, на каждом шаге цикла происходит сначала копирование - потом сдвиг указателей:
*pd = *ps; pd = pd + 1; ps = ps + 1;
Запись *pd++ = *ps++ является более коротким способом записать три строчки выше. Используемая тут операция - постинкремент - увеличивает переменную, возвращая при этом старое значение переменной.
При копировании в обратную сторону - так получается, что указатель указывает на байт, идущий сразу после необработанного блока памяти:
----ssssssss---- ----dddddddd---- ^ ^ | | ps pd
Поэтому, на каждой итерации цикла его сначала сдвигают - а потом уже делают присваивание:
ps = ps - 1; pd = pd - 1; *pd = *ps;
Более коротко это записывается как *--pd = *--ps. используемая операция - предекремент - уменьшает переменную, возвращая новое значение переменной.

Комментариев нет:

Отправить комментарий