在Union(C)中存储函数指针
问题描述:
我有一个'Circle'和'Triangle'的结构。我试图创建两个函数指针的联合,指向在两个结构上运行的两个函数。我认为其余的应该是自我解释。在Union(C)中存储函数指针
的代码如下:
struct Triangle
{
char color;
char shade;
int base;
int height;
};
struct Circle
{
char color;
char shade;
int radius;
};
void drawCircle(struct Circle* x);
float areaCircle(struct Circle* x);
void drawTriangle(struct Triangle *x);
float areaTriangle(struct Triangle* x);
在main()函数:
typedef union uCircle
{
void(*draw)(struct Circle*);
float(*area)(struct Circle*);
}uc;
typedef union uTriangle
{
void(*draw)(struct Triangle*);
float(*area)(struct Triangle*);
}ut;
uc(*vtc[2])(struct Circle*);
vtc[0].(*draw) = &drawCircle;
vtc[1].(*area) = &areaCircle;
ut(*vtt[2])(struct Triangle*);
vtt[0].(*draw) = &drawTriangle;
vtt[1].(*area) = &areaTriangle;
那种遇到错误的是这些:
Structs.c:117:9: error: expected identifier before ‘(’ token
vtc[0].(*draw) = &drawCircle;
Structs.c:118:9: error: expected identifier before ‘(’ token
vtc[1].(*area) = &areaCircle;
^
Structs.c:121:9: error: expected identifier before ‘(’ token
vtt[0].(*draw) = &drawTriangle;
^
Structs.c:122:9: error: expected identifier before ‘(’ token
vtt[1].(*area) = &areaTriangle;
看起来像这是我似乎无法识别的一些简单的语法错误。我究竟做错了什么?
答
第一件事。 取而代之的是:如果你打算通过正常的工会变量来使用这些函数指针
uc vtc;
vtc.draw = drawCircle;
vtc.area = areaCircle;
:
uc(*vtc)(struct Circle*);
vtc.(*draw) = &drawCircle;
vtc.(*area) = &areaCircle;
你应该使用这个。
第二件事。请记住,工会一次只能存储一个成员。
所以,与其这样
vtc.draw = drawCircle;
vtc.area = areaCircle;
将有
vtc.area = areaCircle;
易于接受和覆盖vtc.draw
效果。
换句话说,在初始化vtc.area
后访问vtc.draw
将导致未定义的行为并且可能发生奇怪的事情。
如果您想同时使用draw
和area
,请改用结构。
答
您的语法错误。指针功能的指定不使用任何*
这样的代码:
vtc.draw = drawCircle;
而且你的做法是错误的,包含函数指针的uc
和ut
变量应该是struct
,不union
。我想你试图重新发明closures。
您可能想定义一个包含函数的结构,即vtable。像
struct object;
struct methods_st {
void (*drawer)(struct object*);
double (*area)(struct object*);
};
struct object {
struct methods_st* vtable;
char color, shade;
};
struct circle {
struct object head;
int radius;
};
static void circle_drawer (struct object*oc) {
struct circle*c = (struct circle*)oc;
draw_circle_of_radius (c->radius);
}
static float circle_area (struct object*oc);
static struct method_st circle_vtable = { circle_drawer, circle_area };
东西,如果这是不够清晰,看里面Gobject从GTK。
你为什么试图使用结构这样的联合? Union一次只能存储一个成员。 – askmish 2014-09-25 05:16:16
你打算有'uc(* vtc)(struct Circle *);'声明一个变量'vtc',它是一个函数指针,返回'ut'并把一个指向'struct Circle'的指针作为单个参数?因为那正是你得到的。 *'vtc'和'vtt'都是函数指针。我怀疑这不是你的意图。 – WhozCraig 2014-09-25 05:16:19
由于绘图和区域的函数签名是不同的(void vs float),我不能简单地创建一个函数指针数组(一种类型)。为了使它工作,我试图创建这两个函数指针的联合。这个联合是作为函数指针的类型。 – Prasad 2014-09-25 05:19:44