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

在Union(C)中存储函数指针,c,C,我有一个“圆”和“三角形”的结构。我试图创建两个函数指针的并集,它们分别指向在两个结构上运行的两个函数。我认为其余的应该不言自明 代码如下: struct Triangle { char color; char shade; int base; int height; }; struct Circle { char color; char shade; int radius; }; void drawCircle(struct Circ

我有一个“圆”和“三角形”的结构。我试图创建两个函数指针的并集,它们分别指向在两个结构上运行的两个函数。我认为其余的应该不言自明

代码如下:

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);
在主要功能方面:

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;

看起来是一些简单的语法错误,我似乎认不出来。我做错了什么?

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

 vtc.draw = drawCircle;
您的方法是错误的,包含函数指针的uc和ut变量应该是struct,而不是union

我猜你是在试图重新发明

您可能需要定义一个包含函数的结构,即。差不多

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查看内部。

第一件事。 与此相反:

uc(*vtc)(struct Circle*);
vtc.(*draw) = &drawCircle;
vtc.(*area) = &areaCircle;
您应该使用以下选项:

uc vtc;
vtc.draw = drawCircle;
vtc.area = areaCircle;
如果您打算通过标准联合变量使用这些函数指针

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

所以,不是这个,

vtc.draw = drawCircle;
vtc.area = areaCircle;
将产生

vtc.面积=面积圆;可访问并覆盖vtc.draw

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


如果你想同时绘制和绘制面积,那么就用一个结构来代替。

你为什么要像结构一样使用并集呢?联合一次只能存储一个成员。您是否打算使用uc*vtcstruct Circle*;声明一个变量vtc,该变量是指向返回ut并将指向结构圆的指针作为单个参数的函数的指针?因为这正是你得到的。vtc和vtt都是函数指针。我怀疑这不是你的意图。因为draw和area的函数签名是void和float的不同,所以我不能简单地创建一种类型的函数指针数组。为了让它工作,我尝试创建这两个函数指针的并集。此联合是函数指针的类型。联合的所有成员占用相同的空间。当你执行第二个任务时,如果它成功了,你会覆盖第一个任务。您需要的是原始结构中的两个函数指针。我已将vtc和vtt修改为各自联合类型的数组。现在应该没有任何覆盖问题,只是语法错误。OP已更新。事实上,函数指针应该位于原始的三角形和圆形结构中。我尝试了您的方法,得到了以下结果:structs.c:117:5:错误:请求在非结构或并集的内容中“绘制”成员。此外,使用并集是问题定义的一部分