Если ваша функция получает указатель в качестве аргумента и имеет этот прототип:
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
, а не исходное выражение, используемое в качестве аргумента Параметр функции.