【问题标题】:How do I pass type-generic function pointers?如何传递类型泛型函数指针?
【发布时间】:2019-04-08 06:32:25
【问题描述】:

这是我的代码:

 #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,虚部取值为 0。有什么办法可以解决这个问题,还是在将 csqrt 和所有其他复杂函数作为参数传递时,我需要坚持使用它们吗?

我相信代码的行为方式是这样的,因为 tgmath 函数是作为函数宏实现的,并且只有在名称后跟 () 时才会扩展。

【问题讨论】:

  • 一般来说,函数指针必须与它所指向的函数具有完全相同的类型。否则,参数和结果将被查找/放入错误的位置。
  • 是的,但是 tgmath 应该通过它的参数选择正确的函数,就像 C++ 重载一样,不是吗?
  • @DarkAtom tgmath 使用 _Generic 宏。您不能指向宏。
  • 有趣的编码目标,但不可能。如果高级别目标已知,则存在替代方案。

标签: c


【解决方案1】:

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_functionvariant_complex_datum 来获得你想要的东西。

...现在,我的建议是对某些variants 的实现有点粗鲁和半途而废。我确信有更复杂和全面的 C 库......哦,是的,给你:

Variant datatype library for C

【讨论】:

    【解决方案2】:

    _Complex double 不是 doublesqrt 采用双精度,而 csqrt 采用 _Complex 双精度。 我没有检查实现,但我想说你传递的实际上是一个指向 sqrt 函数的指针,而不是一个数字。

    【讨论】:

    • 我知道,但我是#includeing tgmath.h,这应该会让编译器从使用的类型中选择正确的函数,就像在 C++ 重载中一样。
    • @MarkBenningfield 实际上,这就是 tgmath 所做的。如果我要使用 _Complex 参数直接从 main 调用 sqrt,它会起作用。
    • @DarkAtom:没错。但是使用函数指针来重定向调用是行不通的,因为 C 编译器不会那样做类型解析。
    • @MarkBenningfield,是的,我在问是否有解决方法。由于函数指针类型的复杂性,我不确定是否可以使用 _Generic 关键字重载 execmathfunc 本身。
    • @DarkAtom:我不认为没有很多乏味的样板文件。而且它会相当脆弱,IMO。
    【解决方案3】:

    我相信代码的行为是这样的,因为 tgmath 函数是作为函数宏实现的,并且只有在名称后跟 () 时才会扩展。

    是的

    有什么办法可以解决这个问题...?

    没有直接的方法。

    使用&lt;tgmath.h&gt;,代码无法提取将使用某种类型的对象调用的函数。

    您可以使用_Generic 编写自己的函数集,但我认为您知道这一点并且正在努力避免它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 2017-07-19
      • 2013-06-13
      • 2019-11-01
      • 2014-09-09
      • 2020-12-03
      相关资源
      最近更新 更多