36

我需要实现一些方法来处理不同类型的数字数组。通常,我会使用泛型来完成这项工作,但由于 C 没有提供它们,我现在尝试使用宏来模拟它们。

这是我正在尝试做的一个例子:

#ifndef TYPE
#define TYPE int
#endif

TYPE get_minimum_##TYPE (TYPE * nums, int len){
    TYPE min = nums[0];

    for (int i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

但是,这不会编译。铿锵声错误信息:

错误:预期的';' 在顶级声明者之后

有没有办法在C中做到这一点?还是我需要手动为每种类型实现这个?

4

3 回答 3

51

您可以在头文件中执行以下操作:

//
// generic.h
//

#define TOKENPASTE(x, y) x ## y

#define GET_MINIMUM(T) TOKENPASTE(get_minimum_, T)

TYPE GET_MINIMUM (TYPE) (TYPE * nums, size_t len){
    TYPE min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

然后#include它在每个所需类型的源文件中,例如:

//
// generic.c
//

#define TYPE int
#include "generic.h"
#undef TYPE

#define TYPE float
#include "generic.h"
#undef TYPE

您可以通过预处理器运行它来测试它:

$ gcc -E generic.c 

int get_minimum_int (int * nums, size_t len){
    int min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

float get_minimum_float (float * nums, size_t len){
    float min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}
于 2013-05-13T12:46:38.650 回答
41

实际上,您能做的最好的事情就是定义一个宏来为给定类型生成函数。

#define define_get_minimum(T) \
T get_minimum_##T(T* nums, int len){ \
    T min = nums[0]; \
    for (int i = 1; i < len; i++) { \
        if (nums[i] < min) { \
            min = nums[i]; \
        } \
    } \
    return min; \
}

然后,您可以调用该宏来定义您需要的特化(使用 C++ 模板,编译器会自动完成类似的事情)。

define_get_minimum(int)
define_get_minimum(double)
define_get_minimum(float)

C++ 编译器自动执行的另一件事是推断您需要的重载函数。你不能在 C 中拥有它,所以你必须告诉你正在使用 it 专业化。您可以使用以下宏为您的函数模拟类似模板的语法(C++<>仅替换为()):

#define get_minimum(T) get_minimum_##T

然后,您应该可以通过以下方式调用它:

int main()
{
    // Define arr as char* array...
    // Do stuff...
    int res = get_minimum(int)(arr, 3);
}

我没有测试这段代码,但它应该可以工作。

于 2013-05-13T13:56:18.237 回答
3

您还可以使用函数指针(函数指针数组),而不是 switch 语句,并将 switch 的参数作为索引传递给数组。

于 2017-07-28T23:05:56.750 回答