Наткнулся на код, по которому у меня возникает пару вопросов, если ответите, то буду признателен
#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 память выделяется непосредственно в функции, а потом усекается. Для варианта из третьего вопроса эта ответственность ляжет на вызывающую сторону. Преимущества и недостатки есть у обоих способов. Всё зависит от того, как их использовать.
Комментариев нет:
Отправить комментарий