【问题标题】:C multiple types functionC 多类型函数
【发布时间】:2016-04-16 10:35:32
【问题描述】:

我想用 C 编写一些函数,但它们必须可用于所有数字类型(int、float、double)。什么是好的做法?在 void 上使用指针(当然还有指向函数的指针)?还是为每种类型编写不同的函数?

例如:

 float func(float a, float b) {
   return a+b;
 }

【问题讨论】:

  • C 没有泛型或模板。如果您确实需要,您可以使用宏获得类似的效果。

标签: c function types polymorphism


【解决方案1】:

在 C++ 中,这可以通过模板或函数重载轻松完成。 我在 C 中知道的唯一方法是为每种类型编写不同的函数。

您可以使用带有两个void* 的函数并使用它们进行计算,但这对用户来说极具误导性:如果有一个特殊类型可以使用另一个版本的函数但用户使用void*功能?这可能会导致大问题,不建议这样做。

对于这方面的实际示例,请查看位于stdlib.h 中的标准字符串转换函数atoiatolatof。每个变量类型一个函数。

【讨论】:

    【解决方案2】:

    由于 C 没有像 C++ 那样的多重分派(函数重载)(编辑:除非您使用具有 _Generic 的 C11),因此您必须为每种类型的函数命名不同,例如 funcInt(int a, int b); funcFloat(float a, float b);

    使用允许typeof()kind of fake it 的GCC 样式语句表达式宏。

    【讨论】:

      【解决方案3】:

      如果您可以使用 C11,_Generic 可以提供帮助:

      #include <stdio.h>
      
      int ifunc(int a, int b) { return a+b; }
      float ffunc(float a, float b) { return a+b; }
      double dfunc(double a, double b) { return a+b; }
      
      #define func(x, y) \
         _Generic((x), int: ifunc, float: ffunc, double: dfunc, default: ifunc)(x, y)
      
      int main(void)
      {
          {
              int a = 1, b = 2, c;
              c = func(a, b);
              printf("%d\n", c);
          }
          {
              float a = .1f, b = .2f, c;
              c = func(a, b);
              printf("%f\n", c);
          }
          {
              double a = .1, b = .2, c;
              c = func(a, b);
              printf("%f\n", c);
          }
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        旧式 C 方式是使用联合和鉴别器:

        union multi_num {
            uint32_t  small_num;
            uint64_t  large_num;
            float     float_num;
        };
        
        struct multi_type {
            int discriminator;
            union multi_num val;
        };
        
        int
        add_fun (struct multi_type var1, struct multi_type var2, struct multi_type *ret_val)
        {
        
            if (var1.discriminator != var2.discriminator) {
                return -1;
            }
            ret_val->discriminator = var1.discriminator;
            switch (var1.discriminator) {
                case 1:
                    ret_val->val.small_num = var1.val.small_num + var2.val.small_num;
                    break;
                case 2:
                    ret_val->val.large_num = var1.val.large_num + var2.val.large_num;
                    break;
                case 3:
                    ret_val->val.float_num = var1.val.float_num + var2.val.float_num;
                    break;
            }
        
            return 0;
        }
        

        那么你可以这样称呼它:

        struct multi_type var1, var2, var3 = {0};
        
        var1.discriminator = 1;
        var2.discriminator = 1;
        
        var1.val.small_num = 1;
        var2.val.small_num = 12;
        ret = add_fun(var1, var2, &var3);
        
        if (0 == ret) {
            printf("add worked, ret is %d\n", var3.val.small_num);
        } else {
            printf("add failed\n");
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-24
          • 1970-01-01
          相关资源
          最近更新 更多