我可以理解 avoid**
可能在内存中的样子,但我想知道我是否正确使用它。我在下面描述的内容是否存在任何基本缺陷?例如,虽然我可以说“它对我有用”,但我是否以某种方式创建了糟糕/不可移植的代码?
所以我有一个小行星克隆。可以发射子弹的实体有 3 个,玩家 ( SHIP *player_1
, SHIP *player_2
) 和 UFO ( UFO *ufo
)。当子弹发射时,知道是谁发射的子弹很重要;如果是玩家,当它击中某些东西时,他们的分数需要增加。所以,子弹将存储它属于什么类型的实体 ( owner_type
) 以及直接指向所有者 ( owner
) 的指针:
enum ShipType
{
SHIP_PLAYER,
SHIP_UFO
};
typedef struct Bullet
{
// ...other properties
enum ShipType owner_type;
void **owner;
} BULLET;
然后,当玩家按下按钮或 UFO 看到目标时,将调用以下函数之一:
void ship_fire(SHIP **shipp)
{
BULLET *bullet = calloc(1, sizeof(BULLET));
bullet->owner_type = SHIP_PLAYER;
bullet->owner = (void**)shipp;
// do other things
}
void ufo_fire(UFO **ufop)
{
BULLET *bullet = calloc(1, sizeof(BULLET));
bullet->owner_type = SHIP_UFO;
bullet->owner = (void**)ufop;
// do other things
}
...它们可能被称为,例如,像这样:
ship_fire(&player_1);
最后,当子弹击中目标(例如小行星)时,我们取消对所有者的引用。如果它是一艘船,我们可以在那里增加分数。
void hit_asteroid(ASTEROID *ast, BULLET *bullet)
{
SHIP *ship_owner;
if (bullet->owner_type == SHIP_PLAYER && *bullet->owner != NULL)
{
ship_owner = (SHIP*)*bullet->owner;
ship_owner->score += 1000;
}
}
这似乎是一个合理的方法吗?就像我说的,它对我有用,但我只有几个月的 C 经验。
最后一点:为什么我不使用 avoid*
而不是 a void**
?因为我想避免悬空指针。换句话说,假设它player_1
死了并且被释放了,但他们的子弹继续前进并击中了一颗小行星。如果我只有一个void*
,则该hit_asteroid
函数无法知道bullet->owner
指向已取消分配的内存。但是使用 a void**
,我可以有效地检查它是否为 NULL;如果player_1
是 NULL,那么*bullet->owner
也将是 NULL。
编辑:到目前为止,所有受访者都同意在这里使用 void** 可能不是必需的,因为我可以避免悬空指针问题(例如,仅通过静态分配基础对象)。他们是正确的,我会重构。但是我仍然有点想知道我是否以某种方式使用了 void** 可能会破坏某些东西,例如在内存分配/强制转换方面。但我想如果没有人举手宣布它有故障,它至少类似于技术上可行的东西。
谢谢!