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.
精彩评论