我需要编写一个函数来总结一个我不知道它的类型的数值数组。 该函数可以接收数组的大小和每个变量的大小。 我被告知我应该使用无效指针,但我不知道该怎么做。 顺便说一句,我不能使用宏。 谢谢!
答案 0 :(得分:2)
说实话,整个练习听起来很愚蠢。
您需要使用具有与qsort()
大致相似的界面的函数:
void calculate_sum(const void *ptr,
const size_t size,
const size_t num,
void *sum,
void (*sum_func)(void *, const void *))
{
size_t i;
for (i = 0; i < num; i++)
sum_func(sum, (void *)((char *)ptr + size * i));
}
调用者仍然需要每种类型的求和函数,比如说
void sum_int(void *acc, const void *val)
{
*(int *)acc += *(const int *)val;
}
void sum_float(void *acc, const void *val)
{
*(float *)acc += *(const float *)val;
}
假设调用者有几个数组,比如
float fdata[50];
double ddata[40];
要计算它们的总和,需要
float fsum;
double dsum;
fsum = 0.0f;
calculate_sum(fdata, sizeof fdata[0], 50, &fsum, sum_float);
dsum = 0.0;
calculate_sum(ddata, sizeof ddata[0], 40, &dsum, sum_double);
该接口适用于qsort()
之类的内容 - 尽管即使qsort()
也可以从调用者能够传递第三个参数void *
中获益,并将其用于比较函数。在我看来,排序练习对于这种界面非常有效,特别是当与某种小struct
一起使用时。
在这里,我认为练习会使学习者走向错误的方向:这不是算术运算的正确接口。它产生的企业代码过于复杂和缓慢,专为工作安全而设计;不可读,可维护,良好的代码。
算术的东西,比如求和,在我看来需要专用函数。但这并不意味着您必须复制粘贴大量代码;我们可以在这里使用预处理器。
让我们看看如何使用C11 _Generic
语义实现求和:
#include <stdlib.h> /* For size_t type */
#define DEFINE_SUM_FUNC(type, funcname) \
type funcname (const type *data, size_t count) \
{ \
const type *ends = data + count; \
type sum = 0; \
while (data < ends) \
sum += *(data++); \
return sum; \
}
DEFINE_SUM_FUNC(float, float_sum);
DEFINE_SUM_FUNC(double, double_sum);
DEFINE_SUM_FUNC(short, short_sum);
DEFINE_SUM_FUNC(int, int_sum);
DEFINE_SUM_FUNC(long, long_sum);
#define array_sum(array, count) _Generic((array)[0], \
float: float_sum((const float *)(array), (size_t)(count)), \
double: double_sum((const double *)(array), (size_t)(count)), \
short: short_sum((const short *)(array), (size_t)(count)), \
int: int_sum((const int *)(array), (size_t)(count)), \
long: long_sum((const long *)(array), (size_t)(count)) )
DEFINE_SUM_FUNC(type, funcname)
宏评估函数定义。该函数计算数组元素的总和。 (此实现使用指针方法。)
现在,如果您拥有与以前相同的两个数组float fdata[50];
和double ddata[40];
,则可以调用
fsum = array_sum(fdata, 50);
dsum = array_sum(ddata, 40);
请注意array_sum()
适用于数组和指针。也就是说,如果您有float *fdata;
或const double *ddata;
,则上述两行可以正常使用。
在C11之前的代码中,您可以删除array_sum()
宏,并自行调用特定于类型的函数:
fsum = float_sum(fdata, 50);
dsum = double_sum(ddata, 40);
(GCC确实提供了一个__builtin_types_compatible_p()
扩展程序,即使没有array_sum()
,也可以用来构建_Generic()
宏。)