简体   繁体   English

您可以在运行时将指向结构的void指针转换为特定的结构类型吗?

[英]Can you cast a void pointer to a struct to a specific struct type at runtime?

I have a struct defined like this: 我有一个像这样定义的结构:

struct GameState {
    int score;
    int moves;
    bool won;

    void *metadata;
};
typedef struct GameState GameState;

The metadata pointer will point to another struct of a type decided at runtime. 元数据指针将指向运行时确定的另一种类型的结构。 For example it might be: 例如,它可能是:

struct KlondikeMetadata{
    bool draw3;
    int drawcount;
};
typedef struct KlondikeMetadata KlondikeMetadata;

Or maybe: 或者可能:

struct FreeCellMetadata{
    int reserveCells;
};
typedef struct FreeCellMetadata FreeCellMetadata;

The actual metadata struct used depends on the game the user is playing. 使用的实际元数据结构取决于用户正在玩的游戏。 99% of the time this isn't a problem because I know what game the user is playing. 99%的时间这不是问题,因为我知道用户正在玩什么游戏。 However, there are cases where I don't (and can't) know this. 但是,在某些情况下我不知道(也不知道)。

My question is, is there a way to determine or specify the correct metadata type at runtime? 我的问题是,有没有办法在运行时确定或指定正确的元数据类型?

For example if I could add a property to the GameState struct indicating that the metadata value is of type KlondikeMetadata and use that to cast the metadata to that type, I think I'd be golden. 例如,如果我可以向GameState结构添加一个属性,以指示元数据值是KlondikeMetadata类型,并使用该属性将元数据转换为该类型,我想我会很高兴。 Is there a way to do this? 有没有办法做到这一点? Is there a way to specify a type and cast a variable at runtime in C? 有没有一种方法可以在C中运行时指定类型并强制转换变量?

You're going to have to encode it yourself. 您将需要自己对其进行编码。

The easiest solution is to declare an enumeration: 最简单的解决方案是声明枚举:

typedef enum {
 GameType_Klondike,
 GameType_FreeCell,
} GameType;

then add a field of that type before the pointer: 然后在指针前添加该类型的字段:

GameType game_type;
void     *metadata;

Of course, this means you're going to have to set the game_type field when you initialize metadata , to remember the type. 当然,这意味着您在初始化metadata时必须设置 game_type字段,以记住类型。

You can also go a bit object-oriented, and have the GameType be part of the metadata: 您还可以有点面向对象,并将GameType包含在元数据中:

struct Metadata {
 GameType gametype;
};

struct FreeCellMetadata {
 struct Metadata meta;
 /* rest of fields here */
};

struct KlondikeMetadata {
 struct Metadata meta;
 /* rest of fields here */
};

Then you can cast your void * to struct Metadata * , and inspect the gametype field before casting the pointer to the proper type. 然后,您可以将void *struct Metadata * ,并在将指针转换为正确类型之前检查gametype字段。

For bonus points, use a union: 对于奖励积分,请使用联盟:

struct Metadata {
 GameType type;
 union {
 struct KlondikeMetadata klondike;
 struct FreecellMetadata freecellL;
 } game;
};

Again, of course this requires you to maintain the data, ie when you initialize a struct KlondikeMetadata you must remember to set its gametype field, and so on. 同样,当然,这需要您维护数据,即,在初始化struct KlondikeMetadata ,必须记住设置其gametype字段,依此类推。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM