У меня есть структура, которая определяется как

typedef struct
{
    int id;
    char* name;
    float percentage;
}student_t;

И в данной функции

void student_tDeleter(void* val_ref) {
    
}

Я понимаю, что если функция должна была принимать void * ptr в качестве параметра, мне нужно было выполнить приведение типа, чтобы получить доступ к ее переменным-члену, но следующий код по какой-то причине не будет работать

void student_tDeleter(void* val_ref) {
    free((student_t*)val_ref->id);
    free((student_t*)val_ref->name);
    free((student_t*)val_ref->percentage);
    free(val_ref)
    val_ref = NULL;
}

Компилятор сообщает, что «предупреждение: разыменование void * ошибка указателя: запрос элемента« id / name / percent »в чем-то, кроме структуры или объединения.

Я подумал, что это круглые скобки. Поэтому я добавил две лишние круглые скобки

void student_tDeleter(void* val_ref) {
    free(((student_t*)val_ref)->id);
    free(((student_t*)val_ref)->name);
    free(((student_t*)val_ref)->percentage);
    val_ref = NULL;
}

Но компилятор говорит, что

  free(((student_t*)val_ref)->id);
error: incompatible type for argument 1 of ‘free’
  free(((student_t*)val_ref)->percentage);
 note: expected ‘void *’ but argument is of type ‘float’
 extern void free (void *__ptr) __THROW;

Как мне правильно освободить () участников структуры? Любой ответ приветствуется.

0
Alex Hu 14 Окт 2021 в 19:36

3 ответа

Лучший ответ

Приоритет оператора

-> превосходит каст .

(student_t*)val_ref->id
// is like
(student_t*)(val_ref->id)

Вместо этого используйте

((student_t*)val_ref)->id

Бесплатные указатели

@Vlad из Москвы красиво указывает, что код не должен пытаться "освободить" float или int.


Восстановленный код

Поскольку free(NULL) в порядке, позвольте нам также разрешить student_tDeleter(NULL).

void student_tDeleter(void* val_ref) {
  if (val_ref) {
    free(((student_t*)val_ref)->name);
    free(val_ref)
  }
}
3
chux - Reinstate Monica 14 Окт 2021 в 16:49

Члены данных id и percentage не являются указателями.

typedef struct
{
    int id;
    char* name;
    float percentage
}student_t;

Поэтому нет смысла применять функцию free к объектам типа int и float.

Если элемент данных name указывает на динамически выделяемую память, вам необходимо написать

free( ( ( student_t * )val_ref )->name );

А потом

free(val_ref)

Обратите внимание, что приведение типов является унарным оператором, а оператор -> - постфиксным оператором, имеющим более высокий приоритет, чем унарные операторы.

1
Vlad from Moscow 14 Окт 2021 в 16:44

Члены вашей структуры, не выделяемые динамически, будут обрабатываться free структурой. Вам нужно только отдельно освободить любые динамически выделяемые элементы структуры.

Например:

typedef struct a {
    int b;
    char *c;
} a_t;

a_t * create_a() {
    a_t *new_a = malloc(sizeof(a_t));

    new_a->b = 42;
    new_a->c = malloc(new_a->b);

    return new_a;
}

void delete_a(void *d) {
    a_t *a = (a_t *)d;

    free(a->c);
    free(a);
}
1
Chris 14 Окт 2021 в 16:46