Как создать функцию, которая принимает параметр неизвестного типа В C?
скажем, у меня есть следующий код:
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);
3 ответов
у меня есть две идеи:
[1] передают void
указатель на переменную / объект и введите cast it в функции.
[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 */
}
.
.
.
что-то вроде этого.
вы можете хэш определения FLOAT
и INT
и другие как уникальные значения.
или просто
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 */
}
если у вас есть 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);
}
вызовы так:
struct test* get_t(int);
struct test* t1;
r1(&t,get_t);
(вам не нужно использовать &
на функции, они распадаются на указатели автоматически, как массивы). Это проверяет, что t
является указателем, и это get_t
является функцией, возвращающей этот тип указателя. _varp_
технически не требуется, но сохраняет оценку аргумента в правильном порядке.
Edit:
если у вас нет 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);
}
вызовы так:
struct test* get_t(int);
struct test* t1;
r1(struct test*,&t,get_t);
не совсем так безопасно и более избыточно, но все же довольно хорошо.