9

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

提前致谢!

4

6 回答 6

7

C 中没有标准的函数重载(也没有模板),但您可能可以查看“类似 printf”的函数(或可变参数函数),也许它们可以满足您的需求。如果有的话,它们允许灵活的参数列表。

这里有一个这样的函数示例,它采用可变大小的整数数组。

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

iterate("char", some_char_array); // for char arrays/strings

或者

iterate("int", some_int_array); // for integer arrays

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*);

        va_end(ap);
        return strlen(array);
    }
    else if (strcmp(format, "int") == 0)
    {
        int j = -1;
        int* int_array = va_arg(ap, int*);
        while (int_array[++j] != -1)
                    ;   
        va_end(ap);  
        return j;
    }
    va_end(ap);
    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;
}

这打印:

$ ./a.out 
6
6
于 2013-07-16T02:52:12.470 回答
5

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

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

#define sizeof_array(X) \
    _Generic (*(X), \
              char: sizeof_char_array, \
              default: sizeof_int_array) (X)

(我什至没有 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) */

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

#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))

在数组的情况下,以下表达式为真:

(void *)arr == &arr

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

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

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

于 2013-07-16T03:07:50.403 回答
4

答案很简单。你确实需要一个函数来完成这个任务。试试这段代码

#define len(array) sizeof(array)/sizeof(*array)

就是这样。

重要说明:正如评论中所指出的,这不适用于动态分配的数组。

于 2013-12-22T06:04:27.160 回答
2

你应该让你的函数参数接受一个void *类型。这样,您可以传入不同类型的数据,并将其类型转换为您想要的数据。但是,您确实需要注意,因为无法保证正确“猜测” avoid*指向的类型。

于 2013-07-16T02:50:22.980 回答
2

无论哪种情况,您都需要某种类型推断系统来告诉 C 编译器要调用哪个函数。这意味着,您需要事先知道您可能作为参数发送给您的“超级函数”的数组类型。

C 中没有“自动类型推断”可以让您在运行时反映数据的类型。更好的是,您可能必须编写自己的运行时环境才能做到这一点。

一个稍微简单的hackish方式来做到这一点:

#include <stdio.h>

size_t GetLengthOfArray(size_t sizeOfOneElementInArray, size_t sizeOfTheArrayInBytes)
{
   return sizeOfTheArrayInBytes/sizeOfOneElementInArray; 
}
int main(int argc, char *argv[])
{
   char cArr[10] = {'A','B','C','D','E','F','G','H','I','J'};
   int iArr[5] = {10,20,30,40,50};
   printf("%d is the length of cArr\n%d is the length of iArr",GetLengthOfArray(sizeof(cArr[0]),sizeof(cArr)),
                                                               GetLengthOfArray(sizeof(iArr[0]),sizeof(iArr)));
   return 0;
}
于 2013-07-16T03:02:51.777 回答
1

这不太可能,但你可以建立一个标记工会

typedef struct {
    union {
        ssize_t i;
        double d;
        char *s;
    } unknown;
    char identity;
} Dynamic;

或者您可以使用 void 指针:

typedef struct {
  void *unknown;
  char identity;
} Dynamic;
于 2019-11-13T18:10:12.380 回答