如何在 C 中创建一个接受未知类型参数的函数?

发布于 2024-11-07 21:18:16 字数 318 浏览 0 评论 0 原文

假设我有以下代码:

struct test* t1;
t1 = get_t(1);

... 其中 get_t 是:

struct test* get_t(int);

如何重构上述代码并将其放入函数中?像下面这样:

void r1(?* t, ?* (fn*)(int)) {
    t = fn(1);
}

/* ... */

struct test* t1;
r1(t1, &get_t);

Say I have the following code:

struct test* t1;
t1 = get_t(1);

... where get_t is:

struct test* get_t(int);

How can I refactor the above code and put it in a function? Something like the following:

void r1(?* t, ?* (fn*)(int)) {
    t = fn(1);
}

/* ... */

struct test* t1;
r1(t1, &get_t);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

稚然 2024-11-14 21:18:16

使用void *param,一个指向任何东西的指针......在glib中通常用作gpointer

use void *param, a pointer to anything ... commonly used in glib as gpointer

才能让你更想念 2024-11-14 21:18:16

我有两个想法:

[1] 将 void 指针传递给变量/对象,并在函数中对其进行类型转换。

[2] 将所有数据类型与整数数据类型进行联合,该联合将标识联合中的哪个数据类型变量确实保存实际数据。 void * 传递

struct _unknown {
   union {
      int a;
      float b;
      char c;
      double d;
   } data;
   int type;
} unknown;
.
.
.
if (unknown.type == FLOAT)
{
  /* Process variable b */ 
}
else if (unknown.type == INT)
{
 /* Process variable a */
}
.
. 
.

将此联合作为值或像这样的

。您可以将 FLOATINT 以及其他值定义为唯一值。

或者简单地

struct _unknown {
  void *data;
  int type;
} unknown;
.
.
.
if (unknown == FLOAT)
{
  /* process (float *) data */
}
else if (unknown == INT)
{
  /* process (int *) data */
}
else if (unknown == MY_DATA_TYPE)
{
  /* process (my_data_type *) data */
  /* where my_data_type could be a typedef, or struct */
}

I have two ideas:

[1] Pass void pointer to the variable/object, and type cast it in the function.

[2] Make a union of all datatypes along with an integer datatype which will identify which datatype variable in the union does hold the actual data. Pass this union as value or as void *

struct _unknown {
   union {
      int a;
      float b;
      char c;
      double d;
   } data;
   int type;
} unknown;
.
.
.
if (unknown.type == FLOAT)
{
  /* Process variable b */ 
}
else if (unknown.type == INT)
{
 /* Process variable a */
}
.
. 
.

Something like this.

You can hash define the FLOAT and INT and others as unique values.

Or simply

struct _unknown {
  void *data;
  int type;
} unknown;
.
.
.
if (unknown == FLOAT)
{
  /* process (float *) data */
}
else if (unknown == INT)
{
  /* process (int *) data */
}
else if (unknown == MY_DATA_TYPE)
{
  /* process (my_data_type *) data */
  /* where my_data_type could be a typedef, or struct */
}
等你爱我 2024-11-14 21:18:16

如果你有 gcc,你可以使用这个类型更安全的版本:

#define r1(varp,func) ({ \
    typeof(**varp)* (*_func_)(int); \
    typeof(**varp)* _varp_ = (varp); \
    _func_ = (func); \
    r1_((void**)(_varp_),(void*(*)(int))_func_); \
    })

void r1_(void** varp,void*(*func)(int))
    {
    *varp = func(1);
    }

Call as:

struct test* get_t(int);
struct test* t1;
r1(&t,get_t);

(你不需要在函数上使用 & ,它们会自动衰减为指针,就像数组一样)。这会检查 t 是否为指针,以及 get_t 是否为返回该类型指针的函数。 _varp_ 从技术上讲是不需要的,但可以使参数求值保持正确的顺序。

编辑:

如果你没有 gcc,你仍然可以这样做,但你必须明确提供类型:

#define r1(T,varp,func) do { \
    T*(*_func_)(int); \
    T* _varp_ = (varp); \
    _func_ = (func); \
    r1_((void**)(_varp_),(void*(*)(int))_func_); \
    } while(0)

void r1_(void** varp,void*(*func)(int))
    {
    *varp = func(1);
    }

Call as:

struct test* get_t(int);
struct test* t1;
r1(struct test*,&t,get_t);

不太安全,而且更冗余,但仍然相当不错。

If you have gcc, you can use this more typesafe version:

#define r1(varp,func) ({ \
    typeof(**varp)* (*_func_)(int); \
    typeof(**varp)* _varp_ = (varp); \
    _func_ = (func); \
    r1_((void**)(_varp_),(void*(*)(int))_func_); \
    })

void r1_(void** varp,void*(*func)(int))
    {
    *varp = func(1);
    }

Call as:

struct test* get_t(int);
struct test* t1;
r1(&t,get_t);

(You dont need to use & on functions, they decay to pointers automatically, like arrays). This checks that t is a pointer, and that get_t is a function returning that type of pointer. _varp_ is technically unneeded, but keeps the argument evaluation in the right order.

Edit:

If you don't have gcc, you can still do this, but you have to provide the type explicitly:

#define r1(T,varp,func) do { \
    T*(*_func_)(int); \
    T* _varp_ = (varp); \
    _func_ = (func); \
    r1_((void**)(_varp_),(void*(*)(int))_func_); \
    } while(0)

void r1_(void** varp,void*(*func)(int))
    {
    *varp = func(1);
    }

Call as:

struct test* get_t(int);
struct test* t1;
r1(struct test*,&t,get_t);

not quite as safe, and more redundant, but still fairly good.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文