Передача функции с указателем void в качестве аргумента выдает предупреждение - PullRequest
4 голосов
/ 29 апреля 2019

Я реализовал очередь и хочу функцию, которая печатает ее элементы, независимо от типа.Поэтому я сделал функцию printQueue следующим образом:

void printQueue(queue_t *queue, void (*f)(void *)) {
  node_t *node = (*queue).front;
  while(node != NULL) {
    (*f)(node->item);
    puts("");
    node = (*node).next;
  }
}

Идея состоит в том, что она получит очередь, и функцию для печати элемента из очереди (очередь была реализована, чтобы иметь возможность хранить любой видэлемента).Таким образом, эта функция будет перебирать очередь и вызывать эту функцию для печати каждого из ее элементов.

Затем я сделал функцию для печати массивов целых, которые имеют свой собственный размер в своем первом элементе следующим образом:

void printSpecialIntArray(int *array) {
  int i;
  for(i=0; i<array[0]; i++) {
    printf("%d ", array[i]);
  }
}

Однако, если я инициализирую очередь, скажем Q с таким видоммассивов и вызова printQueue(Q, printSpecialIntArray), кажется, работает как задумано, но я получаю предупреждение:

warning: passing argument 2 of ‘printQueue’ from incompatible pointer type [-Wincompatible-pointer-types]
   printQueue(Q, printSpecialIntArray);
                   ^~~~~~~~~~~~
In file included from main.c:3:0:
queue.c:32:6: note: expected ‘void (*)(void *)’ but argument is of type ‘void (*)(int *)’
 void printQueue(queue_t *queue, void (*f)(void *)) {

Почему происходит это предупреждение и как его можно исправить?Есть ли более чистый способ сделать это?

Также, если вам интересно, я использую массив, который имеет свой собственный размер в качестве элемента, потому что я реализую симулятор процесса, и эти "Special intмассивы "на самом деле должны представлять процесс.Если вы знаете более понятный способ сделать это, я также был бы признателен, если бы вы включили его в свой ответ / комментарий.

Ответы [ 2 ]

3 голосов
/ 29 апреля 2019

Ваша подпись функции не совпадает. Вам необходимо предоставить ожидаемую подпись и привести указатель в соответствии с вашими потребностями:

void printSpecialIntArray(void *arr) {
  int array = (int *)arr;
  int i;
  for(i=0; i<array[0]; i++) {
    printf("%d ", array[i]);
  }
}
3 голосов
/ 29 апреля 2019

Сообщение об ошибке очень прямолинейно.Функция void printQueue(queue_t *queue, void (*f)(void *)) ожидает, что f будет указателем на функцию, возвращающую void и принимающую ровно один аргумент, и ее тип должен быть void*.Функция printSpecialIntArray не выполняет этого, поскольку ее аргумент равен int*.

. Одним из решений является изменение f, чтобы вместо void* в качестве аргумента использовалось int*.Другое решение - переписать printSpecialIntArray:

void printSpecialIntArray(void *a) {
  int *array = (int*) a;
  int i;
  for(i=0; i<array[0]; i++) {
    printf("%d ", array[i]);
  }
}

Примечание:

Даже если указатель void можно безопасно преобразовать в указатель int, функция f все еще должна быть функция, которая принимает пустой указатель в качестве аргумента.Проблема не в аргументе, а в объявлении функции.

...