如何制作一个可以接收不同类型参数的c函数



我正在为一个相当旧的软件包(NWChem)开发一个模块,不确定从一对非常常用的函数调用中生成函数的最佳方法。主包中有一组用于操作运行时数据库的函数。我经常一起使用的一对是rtdb_get_infortdb_get,用于提取数据库中某个值的内容信息并获得实际值。这些功能的标题是:

extern int rtdb_get_info(const int, const char *, int *, int *, char [26]);
extern int rtdb_get(const int, const char *, const int, const int, void *);

调用它们的方式是执行以下操作(忽略返回值):

int nelem, ma_type;
char date[26];
rtdb_get_info(rtdb, "nameofrtdbvalue", &ma_type, &nelem, date)
rtdb_get(rtdb, "nameofrtdbvalue", ma_type, array)

其中,rtdb是一个在其他地方设置的整数,用于指定要访问的数据库,而数组是一个要存储"nameofrtdbvalue"中存储的值的数组。在某些情况下,您可能会在进行实际的rtdb_get调用之前先进行array = malloc(nelem * sizeof *array)

目前,我正在使用以下函数来调用这对:

void rtdb_pull(int rtdb, const char *name, void *array) {
int ma_type;
int nelem;
char date[26];
if (rtdb_get_info(rtdb, name, &ma_type, &nelem, date)) {
if (rtdb_get(rtdb, name, ma_type, nelem, array)) 
printf("Retrieved %s from rtdb.n", name);
else 
printf("%s is in rtdb, but not retrievable.n", name);
}
else 
printf("Couldn't get info on %s from rtdb.n", name);
}

这里有一个我将分配东西并调用rtdb_pull的示例方法。在这种情况下,我将从数据库中提取一个3*npointsdoubles的数组,然后将它们传递给其他函数,该函数对coords

double *coords=malloc(sizeof *coords);
int npoints, rtdb;
int i, nloops;
char buf[32];
get_rtdb(&rtdb); //Just something that gets the integer for the runtime database
for (i=0;i<nloops;i++) {
get_npoints(&npoints);
coords=realloc(coords,npoints * sizeof *coords);
rtdb_pull(rtdb,"geometryname",coords);
use_coords(coords);
}
free(coords);

rtdb_pull是我在学习c时编写的第一个函数之一,我注意到我调用它越多,就越有可能出现分段错误,所以我想重写它,但不确定最好的方法。调用它似乎会导致内存泄漏,但我不确定为什么。也许这与我将一个指针传递给一个void*有关,该指针指向为一个doubles数组分配的内存?如果是这样的话,我不知道如何解决这个问题(不断调用这两个函数真的很烦人)。

有什么想法或建议吗?

使用void*没有错,当你需要的时候,它们可以像泛型类型一样工作,这似乎就是你想要的,对吧?

int myfunc(void* data, int op)
{
double *mycoords;
if(op == 1) // a way to control the real type 
mycoords = (double*) data; 
//...
return 0;
}

在函数内部,您可以强制转换或将(void*)转换为所需的类型。

另一种方法是编写一个带有变量参数列表的函数,这是stdarg手册页中的一个示例:

#include <stdio.h>
#include <stdarg.h>
void
foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's':              /* string */
s = va_arg(ap, char *);
printf("string %sn", s);
break;
case 'd':              /* int */
d = va_arg(ap, int);
printf("int %dn", d);
break;
case 'c':              /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %cn", c);
break;
}
va_end(ap);
}

我看不出您的rtdb_pull方法有任何问题,像这样使用void *是完全可以的。所以也许问题出在其他地方:

  • rtdb_get_infortdb_get是否坚如磐石并经过良好测试
  • 在您的代码示例中,循环之后没有看到free( coords );语句,这正常吗

您对rtb_get_info的调用会更新nelem中的值,从上下文来看,我认为这是要存储到数组中的元素数量。无论你如何根据npoints的值来调整数组的大小,你知道这些值是相同的吗?我们看不到npoints是如何设置的。

此外,get_npoints()函数看起来不适合C代码。npoints被声明为int,我不知道它是如何通过调用get_npoints()来更新的,在C++中,我认为它是一个引用,但这是C.

这句话让我很困扰:

double *coords=malloc(sizeof *coords);

coords是指向一个或多个double的指针是可以的,但您必须将它的实际内存分配到某个地方。sizeof *coords是什么意思?您真的希望malloc()的参数是这个数组所需的总字节数,我认为您没有这么做。您还需要将返回的指针强制转换为double*。你使用的是一个非常旧的C编译器,错误检测很差吗?

无论如何,开始清理你的代码,并在你的代码中添加一些注释来解释你想要做什么

相关内容

  • 没有找到相关文章

最新更新