多类型函数(C语言)

4

我想在C语言中编写一些函数,但它们必须适用于所有数字类型(int、float、double)。那么什么是最佳实践?使用void指针(当然还有函数指针)?还是为每种类型编写不同的函数?

例如:

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

C语言没有泛型或模板。如果你真的需要,可以通过宏来实现类似的效果。 - fuz
4个回答

6
如果您可以使用 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;
}

3
由于C语言没有像C++那样的多重分派(函数重载)(除非您使用具有_Generic的C11),因此您必须为每种类型单独命名函数,例如 funcInt(int a, int b); funcFloat(float a, float b);。
或者,可以使用GCC风格的语句表达式宏,允许typeof()有点假装。

2

旧式的C语言方式是使用union和一个区分器:

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");
}

1

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

您可以使用一个接受两个void*参数并对它们进行计算的函数,但这对用户来说非常具有误导性:如果有一种特殊类型,而另一种函数版本可用,但用户使用void*函数会发生什么?这可能会导致严重问题,因此不建议这样做。

关于这一点的实际示例,请查看位于stdlib.h中的标准字符串转换函数atoi, atol, atof。每个变量类型都有一个函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接