在Union(C)中存储函数指针

时间:2014-09-25 05:09:43

标签: c

我有'Circle'和'Triangle'的结构。我正在尝试创建两个函数指针的并集,指向两个函数,每个函数在两个结构上运行。我认为其余部分应该是自我解释的。

代码如下:

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;

看起来这是一些我似乎无法识别的简单的语法错误。我做错了什么?

2 个答案:

答案 0 :(得分:3)

第一件事。 而不是:

uc(*vtc)(struct Circle*);
vtc.(*draw) = &drawCircle;
vtc.(*area) = &areaCircle;

你应该用这个:

uc vtc;
vtc.draw = drawCircle;
vtc.area = areaCircle;

如果您打算通过普通的union变量使用这些函数指针。

第二件事。 请记住,工会一次存储一名成员。

所以,而不是这个

vtc.draw = drawCircle;
vtc.area = areaCircle;

将具有

的效果

vtc.area = areaCircle;可以访问并覆盖vtc.draw

换句话说,在初始化vtc.draw后访问vtc.area将导致未定义的行为,并且可能会发生奇怪的事情。

如果您同时需要drawarea,请改用结构。

答案 1 :(得分:0)

你的语法错了。指针函数的赋值不使用任何*代码:

 vtc.draw = drawCircle;

你的方法是错误的,包含函数指针的ucut变量应该是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 };

如果不够清楚,请查看GTK内的Gobject