2013-03-19 3 views
2

У меня есть определенная-структура, как это:Можете ли вы наложить указатель на пустоту на структуру определенного типа структуры во время выполнения?

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

    void *metadata; 
}; 
typedef struct GameState GameState; 

Указатель метаданных будет указывать на другую структуру такого типа, решили во время выполнения. Например, это может быть:

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

Или, может быть:

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

Фактическая структура метаданных используется в зависимости от игры играет пользователь. 99% времени это не проблема, потому что я знаю, какую игру играет пользователь. Однако есть случаи, когда я не знаю (и не могу) это знать.

Мой вопрос в том, есть способ определить или указать правильный тип метаданных во время выполнения?

Например, если бы я мог добавить свойство к структуре GameState, указывающее, что значение метаданных имеет тип KlondikeMetadata и использовать это для метаданных для этого типа, я думаю, что я был бы золотым. Есть ли способ сделать это? Есть ли способ указать тип и ввести переменную во время выполнения в C?

+0

Мне просто пришло в голову, что я могу просто иметь значение, чтобы указать тип структуры 1: KlondikeMetadata, 2: FreeCellMetadata. И тогда я могу включить это значение и в каждом случае привести (со статическим кодом) к правильному типу. –

+0

Если это только один из двух известных типов, «объединение» может быть приятнее, чем использование «void *» plus cast. Конечно, это требует такой же бухгалтерской отчетности. – FatalError

+0

Интересно. До этого я не знал союзов. Благодарю. В конце концов, мы надеемся, будут десятки этих структур метаданных. В любом случае (объединение или пустота), похоже, примерно столько же работы. –

ответ

7

Вам придется его кодировать самостоятельно.

Самое простое решение объявить перечисление:

typedef enum { 
GameType_Klondike, 
GameType_FreeCell, 
} GameType; 

затем добавить поле этого типа перед указателем:

GameType game_type; 
void  *metadata; 

Конечно, это означает, что вы будете иметь, чтобы комплектgame_type поле, когда вы инициализируете metadata, чтобы запомнить тип.

Вы можете также пойти немного объектно-ориентированные, и имеете GameType быть частью метаданных:

struct Metadata { 
GameType gametype; 
}; 

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

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

Тогда вы можете отдать свой void * в struct Metadata * и осмотреть gametype поля перед заливкой указателя правильный тип.

Для бонусных очков, используйте союз:

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

Опять же, это, конечно, требует, чтобы сохранить данные, т.е. при инициализации struct KlondikeMetadata вы должны помнить, чтобы установить его gametype поле, и так далее.

+0

Я просто думал об этом, на самом деле. Вы сказали это гораздо более красноречиво. Благодаря! –

Смежные вопросы