Фильтр CS50: отразите изображение bmp вдоль горизонтальной оси, используя фильтр отражения - PullRequest
0 голосов
/ 04 марта 2020

В этом задании мне нужно отредактировать фрагмент кода, который фильтрует изображение. Остальная часть кода уже предоставлена ​​и является правильной. Мой код компилируется, но изображение остается неизменным, и я не могу понять, почему.

Я все еще не уверен в распределении памяти. Я не очень понимаю разницу между мальло c и калло c и не знаю, что здесь предпочтительнее. Я включил закомментированную строку кода, чтобы показать, что я пробовал оба способа с одинаковым результатом. Если бы кто-то мог объяснить mallo c и callo c и их назначение в этом контексте, я был бы очень благодарен!

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE(*tmp)[width] = malloc(height * width * sizeof(RGBTRIPLE));
    // RGBTRIPLE(*tmp)[width] = calloc(height, width * sizeof(RGBTRIPLE));
    if (tmp == NULL)
    {
        return;
    }
    for (int i = 0; i < height; i++)
    {
        // Copy integers from old image into new image
        for (int j = 0; j < width; j++)
        {
            tmp[i][j].rgbtRed = image[i][width - (j + 1)].rgbtRed;
            tmp[i][j].rgbtGreen = image[i][width - (j + 1)].rgbtGreen;
            tmp[i][j].rgbtBlue = image[i][width - (j + 1)].rgbtBlue;
        }
    }
    image = tmp;
    free(tmp);
    return;
}

1 Ответ

0 голосов
/ 04 марта 2020

Функция malloc выделяет только память.

Функция calloc выделяет память , а"очищает" память ( установка всех байтов в ноль).

Короче говоря, calloc эквивалентно malloc, за которым следует вызов memset.

Если честно, почти любая приличная книга, учебник или класс должны были содержать эту информацию.


Что касается кода, который вы показываете, вам не нужно использовать calloc, так как вы все равно перезапишете всю память.

Однако существуют другие проблемы с вашим кодом ...

Первое, что вы забыли, что в C все аргументы передаются по значению, что означает, что значение, которое вы используете при вызов функции скопирован , а внутри функции все, что у вас есть, - это копия, с которой можно работать. Так, например, когда вы присваиваете image, вы назначаете только локальную копию переменной. Исходный указатель, который вы использовали при вызове функции reflect, не будет изменен назначением. Чтобы решить эту проблему, вам нужно скопировать память из tmp в image.

Другая проблема заключается в том, что вы набираете free на tmp после назначения image. Если назначение сработало так, как вы хотели (а это не так, см. Выше), тогда оба указатели image и tmp станут недействительными при вызове free (как оба указателя) одинаковы и указывают на одну и ту же память). К счастью, эта проблема является спорным, как только вы решали проблему копирования, и вы можете free указатель tmp без проблем.

...