Как передать типовые указатели на функции? - PullRequest
1 голос
/ 07 апреля 2019

Это мой код:

 #include <stdio.h>
 #include <tgmath.h>

 double complex execmathfunc(double complex val, double complex (*mathfunc)(double complex))
 {
     return mathfunc(val);
 }

 int main()
 {
     double complex val = -1;
     val = execmathfunc(val, sqrt); //if I put csqrt here it works
     printf("%.1f+%.1fi", creal(val), cimag(val));
     return 0;
 }

Этот код работает, если я использую csqrt, и выведет 0.0+1.0i, как и ожидалось, но если я использую обычный sqrt (возлагая надежды на функции общего типа tgmath.h), он выводит мусор значение для действительной части и 0 для мнимой части. Есть ли способ обойти это или мне нужно придерживаться csqrt и всех других сложных функций при передаче их в качестве аргументов?

Я считаю, что код ведет себя так, потому что функции tgmath реализованы как функциональные макросы, и они расширяются только в том случае, если за именем следует ().

Ответы [ 3 ]

1 голос
/ 07 апреля 2019

В C. нет такого понятия, как указатели на типовые родовые функции.

Однако у вас может быть структура указателей для различных релевантных типов, например,


typedef enum  { 
    USE_FLOAT = 0,
    USE_DOUBLE = 1, 
    // USE_LONG_DOUBLE = 2   // maybe you have this one as well
} complex_component_type_selector;

typedef struct {
    union {
        float complex (*float_)(float complex);
        double complex(*double_)(double complex);
    } function_ptr;
    complex_component_type_selector component_type;
} variant_function;

typedef union {
   union {
       float complex float_;
       double complex double_
   } datum;
   complex_component_type_selector component_type;
} variant_complex_datum;

и с этим вы можете передать variant_complex_function вместе с variant_complex_datum, чтобы получить то, что вы хотели.

... Теперь мое предложение немного грубовато и недооценено для некоторых вариантов . Я уверен, что есть библиотеки для C, которые являются более сложными и всеобъемлющими ... о да, вот, пожалуйста:

Библиотека вариантов типа для C

0 голосов
/ 08 апреля 2019

Я считаю, что код ведет себя так, потому что функции tgmath реализованы как функциональные макросы, и они расширяются, только если за именем следует ().

Да

Есть ли способ обойти это ...?

Прямого пути нет.

Используя <tgmath.h>, код не может извлечь функцию, которая будет вызываться с объектом какого-либо типа.

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

0 голосов
/ 07 апреля 2019

A _Complex double не является double, а sqrt принимает удвоение, а csqrt принимает _Complex двойное.Я не проверял реализации, но я бы сказал, что вы передаете то, что на самом деле является указателем на функцию sqrt вместо числа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...