Как узнать, является ли переменная указателем на функцию в C? - PullRequest
2 голосов
/ 08 мая 2020

У меня есть функция типа void(*func)(int), и я получаю указатель на эту функцию, как я могу точно узнать, что указатель действительно относится к этому типу?

if (typeof(pointer) == void(*func)(int)) {
    //do something     
} 

Это правильно?

edit - Я получаю указатель от функции в качестве аргумента и хочу проверить тип указателя внутри этой функции.

Ответы [ 3 ]

4 голосов
/ 08 мая 2020

, если вы получаете указатель на функцию динамически, поэтому попробуйте использовать объединение и переменную флага, чтобы получить его тип, не проверяя что-то сложное

#define type1 1
#define type2 2
union FN
{
void ....
int ....
....
}

typedef struct{
int type;

union FN fn;
} Function;
3 голосов
/ 08 мая 2020

Если ваша функция получает указатель в качестве аргумента и имеет этот прототип:

void my_function(void (*func)(int)) {
    // How can I test if `func` really points to a function taking an `int`?
}

Тогда вы мало что можете сделать внутри тела my_function, чтобы проверить, что func действительно указывает на.

  • вы можете проверить, является ли он нулевым указателем:

    if (!func) { /* NULL was passed */ }
    
  • вы можете проверить, указывает ли он в известную функцию:

    if (func == exit) { /* haha! (*func)(1) will abort */ }
    
  • помимо вышеперечисленного, невозможно сказать, что на самом деле было передано в my_function: это может быть фактическая функция с правильным прототипом или другая функция неявно или явно приводится к ожидаемому типу или даже к какому-либо другому скалярному объекту с приведением.

Если вы хотите написать макрос, расширение которого зависит от типа выражения, вы может использовать новую конструкцию C11 _Generic:

#define IS_VOID_FUNC_OF_INT(func)  _Generic(func, void(*)(int): 1, default: 0)

Но использование этого внутри тела функции my_function всегда будет оценивать как 1: только определенный тип func проверяется _Generic, а не исходное выражение, используемое в качестве аргумента Параметр функции.

3 голосов
/ 08 мая 2020

typeof не входит в стандарт C. Это расширение GNU.

Если вы хотите быть уверены, что что-то относится к определенному типу, вы можете обработать это во время компиляции с помощью _Generic, представленного в C11:

_Generic((pointer), 
    void(*)(int): /* insert your code here */,
)

Если указанный указатель не относится к типу void(*)(int), он не будет скомпилирован.

...