Прототип функции с параметром void*
У меня есть две функции, каждая из которых принимает указатель на разные типы:
void processA(A *);
void processB(B *);
Существует ли тип указателя на функцию, который мог бы содержать указатель на любую функцию без приведения? Я пытался использовать
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
но это не сработало (компилятор жалуется на несовместимую инициализацию указателя).
Редактировать: другая часть кода будет перебирать записи Ps, не зная типов. Этот код будет передавать символ * в качестве параметра. Как это:
Ps[i](data_pointers[j]);
Редактировать: Спасибо всем. В конце я, вероятно, буду использовать что-то вроде этого:
void processA(void*);
void processB(void*);
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
...
void processA(void *arg)
{
A *data = arg;
...
}
3 ответа
Это можно сделать без приведения с помощью объединения:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef union { void (*A)(A *); void (*B)(B *); } U;
U Ps[] = { {.A = processA}, {.B = processB} };
int main(void)
{
Ps[0].A(0); // 0 used for example; normally you would supply a pointer to an A.
Ps[1].B(0); // 0 used for example; normally you would supply a pointer to a B.
return 0;
}
Вы должны вызвать функцию, используя правильное имя члена; этот метод позволяет хранить только один указатель или другой в каждом элементе массива, а не выполнять псевдонимы для странных функций.
Другой альтернативой является использование прокси-функций, которые имеют тип, необходимый при вызове с параметром, который является указателем на char
и это вызывает фактическую функцию с ее надлежащим типом:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef void (*processor_t)();
void processAproxy(char *A) { processA(A); }
void processBproxy(char *B) { processB(B); }
processor_t Ps[] = { processAproxy, processBproxy };
int main(void)
{
char *a = (char *) address of some A object;
char *b = (char *) address of some B object;
Ps[0](a);
Ps[1](b);
return 0;
}
я использовал char *
выше, так как вы заявили, что используете его, но я бы вообще предпочел void *
,
Если ты typedef void (*processor_t)();
тогда это скомпилируется в C. Это потому, что пустой список аргументов оставляет число и типы аргументов функции неуказанными, поэтому этот typedef просто определяет тип, который является "указателем на функцию, возвращающую void, принимая неопределенное количество аргументов неуказанного тип."
Редактировать: Кстати, вам не нужны амперсанды перед именами функций в списке инициализатора. В C имя функции в этом контексте превращается в указатель на функцию.
Это работает, если вы разыгрываете их
processor_t Ps[] = {(processor_t)processA, (processor_t)processB};
Кстати, если ваш код связан с этим типом вещей и switch
Повсюду, чтобы выяснить, какую функцию вам нужно вызвать, вы можете взглянуть на объектно-ориентированное программирование. Лично мне это не очень нравится (особенно C++...), но он отлично справляется с удалением такого рода кода с помощью виртуального наследования.