Страницы

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

среда, 5 февраля 2020 г.

Как работает функция memmove в C?

#c #указатели #память


Всем привет!

Пытаюсь разобраться как работает функция memmove из стандартной библиотеки C. 

Сама функция:

void    *ft_memmove(void *dst, const void *src, size_t len)
{
    const char  *s;
    const char  *lasts;
    char        *d;
    char        *lastd;

    d = dst;
    s = src;
    if (d < s)
        while (len--)
            *d++ = *s++;
    else
    {
        lasts = s + (len - 1);
        lastd = d + (len - 1);
        while (len--)
            *lastd-- = *lasts--;
    }
    return (dst);
}


Помогите, пожалуйста, понять, что происходит в данной части функции:

else
        {
            lasts = s + (len - 1);
            lastd = d + (len - 1);
            while (len--)
                *lastd-- = *lasts--;
        }

    


Ответы

Ответ 1



lasts = s + (len - 1); // Указатель на последний байт блока s lastd = d + (len - 1); // Указатель на последний байт блока d while (len--) // len раз *lastd-- = *lasts--;// выполняем копирование из блока d в блок s // После копирования байта указатели уменьшаются т.е. простое копирование памяти не "слева направо", а "справа налево". Смысл всего действа - чтоб не затереть копированием нужное при перекрывающихся областях памяти.

Ответ 2



Если эта ft_memmove действительно является реализацией (или частью реализации?) стандартной функции memmove, то надо заметить, что реализация функций стандартной библиотеки языка С не обязана быть написана на языке С и не подчиняется требованиям языка С. Если рассматривать приведенный вами участок кода как код на языке С, то он внешне выполняет (пытается выполнять) копирование участка памяти "в обратном направлении" - от старших адресов к младшим. Однако с точки зрения языка С приведенный код делает это неправильно - на последней итерации цикла копирования происходит применение оператора -- к значениям указателей lastd и lasts, потенциально указывающих в этот момент на начала неких массивов. Это формально приводит к неопределенному поведению. Так что с точки зрения формального языка С код является некорректной реализацией memmove. Если этот код действительно позаимствован из реализации стандартной библиотеки, то это не С, а нечто внешне С-подобное. Чтобы говорить о том, что именно он делает, надо знать особенности поведения той платформы для которой этот код написан. Если же это пользовательский код, то вышеуказанная проблема делает его просто некорректным.

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

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