开发者

How can I create a function that takes a parameter of unknown type in C?

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


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


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 */
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜