Страницы

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

пятница, 14 декабря 2018 г.

Недопонимание с кодом

Наткнулся на код, по которому у меня возникает пару вопросов, если ответите, то буду признателен
#include #include
int isOdd(int a) { return (a % 2 != 0); }
unsigned int filter(int *arr, unsigned size, int (*pred)(int), int** out) { unsigned i; unsigned j; *out = (int*) malloc(sizeof(int)*size); for (i = 0, j = 0; i < size; i++) { if (pred(arr[i])) { (*out)[j] = arr[i]; j++; } } *out = (int*) realloc(*out, j*sizeof(int)); return j; }
int main () { int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; unsigned i; unsigned size; int *aOdd = NULL;
size = filter(a, 10, isOdd, &aOdd); for (i = 0; i < size; i++) { printf("%d ", aOdd[i]); }
}
Вопрос №1: Зачем требуются явные преобразования такого вида?
*out = (int*) malloc(sizeof(int)*size); *out = (int*) realloc(*out, j*sizeof(int));
Они же излишни, если я не ошибаюсь.
Вопрос №2: Что происходит в строках, которые я выделил восклицательными знаками?
unsigned int filter(int *arr, unsigned size, int (*pred)(int), int** out) { unsigned i; unsigned j; *out = (int*) malloc(sizeof(int)*size); /* !!!!!!!!!! */ for (i = 0, j = 0; i < size; i++) { if (pred(arr[i])) { (*out)[j] = arr[i]; /* !!!!!!!!!! */ j++; } } *out = (int*) realloc(*out, j*sizeof(int)); /* !!!!!!!!!! */ return j; }
Вопрос №3: Разве не легче было реализовать функцию из вопроса №2 таким образом (просто через указатель, а не через указатель на указатель)
unsigned int filter(int *arr, unsigned size, int (*pred)(int), int* out) { unsigned i; unsigned j; for (i = 0, j = 0; i < size; i++) { if (pred(arr[i])) { *(out + j) = arr[i]; j++; } }
return j; }
Есть ли существенные различия или даже преимущества между функцией из вопроса №2 и функцией из вопроса №3?


Ответ

Вопрос №1: Зачем требуются явные преобразования такого вида?
Для C не нужны. Для C++ необходимы, т.к. в C++ неявное преобразование из void* запрещено.
Вопрос №2: Что происходит в строках, которые я выделил восклицательными знаками?
1) Выделение памяти для size int'ов. 2) Копирование элемента, удовлетворяющего предикату в только что выделенный массив. 3) Отрезаем не заполненный кусок массива данных
Вопрос №3: Разве не легче было реализовать функцию из вопроса
Они дают разный результат
Есть ли существенные различия или даже преимущества между функцией из вопроса №2 и функцией из вопроса №3?
Для варианта из вопроса №2 память выделяется непосредственно в функции, а потом усекается. Для варианта из третьего вопроса эта ответственность ляжет на вызывающую сторону. Преимущества и недостатки есть у обоих способов. Всё зависит от того, как их использовать.

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

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