创建一个接受不同数据类型参数的C函数

She*_*ker 6 c function

我对C编程语言比较陌生,我正在试图弄清楚如何创建一个可以接受不同类型数据作为参数的函数.该函数应该计算并返回字符或整数数组中的元素数.我已经有两个单独的函数可以执行此操作,但我真的希望能够为这两个任务使用一个函数.有没有办法在C中这样做?

提前致谢!

Nob*_*lis 6

在C中没有标准函数重载(也没有模板),但您可能会查看"类似printf"的函数(或可变函数),也许它们可以满足您的需要.如果他们允许灵活的参数列表.

有一个例子在这里这样的功能的,需要一个可变大小整数数组.

也许您可以void iterate(const char* format, ...);使用以下方式使用的函数签名:

iterate("char", some_char_array); // for char arrays/strings
Run Code Online (Sandbox Code Playgroud)

要么

iterate("int", some_int_array); // for integer arrays
Run Code Online (Sandbox Code Playgroud)

Aniket虽然提出了一个很好的观点,但你如何计算整数数组中的元素?如果将int数组作为参数传递,则需要传递大小,这会使计算数组中元素的计数失败(正如您已经知道的那样,即大小).

我假设您不知道大小,但您在数组中有一个终结符值(例如-1).

考虑到上述假设,我已经快速攻击了你所需要的东西.

#include <stdarg.h>
#include <stdio.h>
#include <string.h>

int iterate(const char* format, ...)
{
    va_list ap;
    va_start(ap, format);

    if (strcmp(format, "char") == 0)
    {
        char* array = va_arg(ap, char*);

        return strlen(array);
    }
    else if (strcmp(format, "int") == 0)
    {
        int j = -1;
        int* int_array = va_arg(ap, int*);
        while (int_array[++j] != -1)
                    ;     
        return j;
    }
    return 0;
}

int main()
{
    printf("%d\n", iterate("char", "abcdef"));
    int arr[] = {5, 4, 3, 2, 1, 0, -1};
    printf("%d\n", iterate("int", arr));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这打印:

$ ./a.out 
6
6
Run Code Online (Sandbox Code Playgroud)


jxh*_*jxh 5

所以,让我们假设你的两个函数被调用sizeof_char_arraysizeof_int_array

在 C11 中,有一个名为“通用选择”的新功能,它可以让你用一个相对简单的宏来做你想做的事:

#define sizeof_array(X) \
    _Generic (*(X), \
              char: sizeof_char_array, \
              default: sizeof_int_array) (X)
Run Code Online (Sandbox Code Playgroud)

(我什至没有 C11 实现来对此进行测试,所以请注意空客!)

在 C11 之前,这有时是通过使用规则命名函数的宏来完成的。您可以定义一个宏,该宏将根据宏参数提示调用一个函数或另一个函数:

#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x)

int a[] = { 1, 2, 3, 4, -1 };
char b[] = "abc";

sizeof_array(int, a);   /* macro expands to sizeof_int_array(a) */
sizeof_array(char, b);  /* macro expands to sizeof_char_array(b) */
Run Code Online (Sandbox Code Playgroud)

如果输入参数确实是一个数组,则可以使用宏直接计算其大小:

#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))
Run Code Online (Sandbox Code Playgroud)

对于数组,以下表达式为真:

(void *)arr == &arr
Run Code Online (Sandbox Code Playgroud)

因为数组的地址在内存中的位置与其第一个元素的地址相同。

因此,宏计算:sizeof(arr)/sizeof(arr[0])。由于sizeof运算符报告其参数的大小(以字节为单位),因此计算表达式得出数组中元素的数量。但是,如果您使用哨兵来计算长度,则ARRAY_SZ宏将导致大小至少比为哨兵遍历数组所找到的长度大一。

如果参数不是数组,则表达式会导致除以 0 异常。