#c_sharp #net
Пример: // 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 постфикс? Можете разъяснить подробно?
Ответы
Ответ 1
Все дело в инварианте цикла. Когда идет побайтовое копирование "вперед" - указатели указывают на первый байт еще не обработанной области памяти: ----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. используемая операция - предекремент - уменьшает переменную, возвращая новое значение переменной.Ответ 2
этот метод копирует определенное число(count) байтов из исходного буфера(src) в буфер назначения(dst). *pd++ = *ps++; // Тут присваивает по 1 байту и сдвигает вправо *--pd = *--ps; // И тут сдвиг влево по байтуОтвет 3
// 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 byte* pd = (byte*)dst; //Приводим указатель к типу byte if (ps > pd) { for (; count != 0; count--) *pd++ = *ps++; // Присваиваем текущему блоку (1 байт) в pd // Значение из ps, и сдвигаемся после этого //на 1 байт вправо (и pd и ps) } else if (ps < pd) { for (ps += count, pd += count; count != 0; count--) *--pd = *--ps; // Сдвигаемся на 1 байт влево (и pd и ps) // и присваиваем текущему блоку (1 байт) в pd // Значение из ps } } постинкремент (постфикс по Вашему) - сначала выполняется операция, потом инкремент предекремент (префикс по Вашему) - сначала декримент, потом операция. Но почему именно так сделано, сразу сложно сказать, думаю нужно более подробно изучить код в целом. P.S. Надеюсь правильно понял, т.к. в C# с указателями я не работал, только в C++
Комментариев нет:
Отправить комментарий