值和函数指针的联合
union of value and function pointer
我正在为使用联合而苦苦挣扎。为什么我无法将函数指针传递到联合所在的位置?任何帮助将不胜感激。
编辑:删除了 typedef
#include <stdio.h>
union U {
int(*fnPtr)(int);
int i;
};
enum E {
OPTION_0 = 0,
OPTION_1 = 1
};
int multiply_by_two (int x) {
return 2 * x;
}
int f (int x, enum E e, union U u) {
switch (e) {
case OPTION_0:
/* Return the sum */
return x + u.i;
case OPTION_1:
/* Return 2 * x */
return u.fnPtr (x);
}
}
int main (void) {
int a;
scanf ("%d", &a);
int b = f (a, OPTION_1, &multiply_by_two);
printf ("%d\n", b);
return 0;
}
首先,这个定义是无效的:
union U {
typedef int(*fnPtr)(int);
int i;
};
struct
或 union
中不能有 typedef
。删除 typedef 将为您提供正确的定义:
union U {
int(*fnPtr)(int);
int i;
};
第二个问题在这里:
int b = f (a, OPTION_1, &multiply_by_two);
函数 f
需要 union U
,但您传递给它的是 int (*)(int)
。这些类型不兼容。仅仅因为 union 具有该类型的成员并不意味着您可以在任何要使用 union 的地方使用该类型。您需要创建一个联合,设置适当的字段,然后将其传递给函数。
union U u;
u.fnPtr = multiply_by_two;
int b = f (a, OPTION_1, u);
在主函数中,试试这个:
int main()
{
...
union U myUnion;
myUnion.fnPtr = &multiply_by_two;
int b = f (a, OPTION_1, myUnion);
...
}
另外,联合定义不正确,需要删除typedef
。
只是为了补充其他答案:这通常称为变体数据类型,将枚举类型与 union
一起保留在 struct
中是有意义的,因为您将反正一直在传递它。
所以我建议将两者都放在 struct
:
enum var_type
{
VAR_INT = 0,
VAR_FUNC = 1
};
struct variant
{
// contains the type of the stored value
enum var_type type;
// contains the actual value
union {
int(*fnPtr)(int);
int i;
};
};
然后您可以使用单独的函数来创建每个子类型,以简化实例化:
// wrap the int value in the variant struct
struct variant variant_create_int(int i)
{
return (struct variant){ .type = VAR_INT, .i = i };
}
// wrap the functino pointer in the variant struct
struct variant variant_create_func(int(*fnPtr)(int))
{
return (struct variant){ .type = VAR_FUNC, .fnPtr = fnPtr };
}
意思是你的 main
会做类似的事情:
// create variant of type 'VAR_FUNC'
struct variant var = variant_create_func(&multiply_by_two);
并向前传递 var
结构。
我正在为使用联合而苦苦挣扎。为什么我无法将函数指针传递到联合所在的位置?任何帮助将不胜感激。
编辑:删除了 typedef
#include <stdio.h>
union U {
int(*fnPtr)(int);
int i;
};
enum E {
OPTION_0 = 0,
OPTION_1 = 1
};
int multiply_by_two (int x) {
return 2 * x;
}
int f (int x, enum E e, union U u) {
switch (e) {
case OPTION_0:
/* Return the sum */
return x + u.i;
case OPTION_1:
/* Return 2 * x */
return u.fnPtr (x);
}
}
int main (void) {
int a;
scanf ("%d", &a);
int b = f (a, OPTION_1, &multiply_by_two);
printf ("%d\n", b);
return 0;
}
首先,这个定义是无效的:
union U {
typedef int(*fnPtr)(int);
int i;
};
struct
或 union
中不能有 typedef
。删除 typedef 将为您提供正确的定义:
union U {
int(*fnPtr)(int);
int i;
};
第二个问题在这里:
int b = f (a, OPTION_1, &multiply_by_two);
函数 f
需要 union U
,但您传递给它的是 int (*)(int)
。这些类型不兼容。仅仅因为 union 具有该类型的成员并不意味着您可以在任何要使用 union 的地方使用该类型。您需要创建一个联合,设置适当的字段,然后将其传递给函数。
union U u;
u.fnPtr = multiply_by_two;
int b = f (a, OPTION_1, u);
在主函数中,试试这个:
int main()
{
...
union U myUnion;
myUnion.fnPtr = &multiply_by_two;
int b = f (a, OPTION_1, myUnion);
...
}
另外,联合定义不正确,需要删除typedef
。
只是为了补充其他答案:这通常称为变体数据类型,将枚举类型与 union
一起保留在 struct
中是有意义的,因为您将反正一直在传递它。
所以我建议将两者都放在 struct
:
enum var_type
{
VAR_INT = 0,
VAR_FUNC = 1
};
struct variant
{
// contains the type of the stored value
enum var_type type;
// contains the actual value
union {
int(*fnPtr)(int);
int i;
};
};
然后您可以使用单独的函数来创建每个子类型,以简化实例化:
// wrap the int value in the variant struct
struct variant variant_create_int(int i)
{
return (struct variant){ .type = VAR_INT, .i = i };
}
// wrap the functino pointer in the variant struct
struct variant variant_create_func(int(*fnPtr)(int))
{
return (struct variant){ .type = VAR_FUNC, .fnPtr = fnPtr };
}
意思是你的 main
会做类似的事情:
// create variant of type 'VAR_FUNC'
struct variant var = variant_create_func(&multiply_by_two);
并向前传递 var
结构。