我有一个不寻常的问题。由于我是逆向工程代码,因此我使用的数据结构(顺便说一下这很糟糕)无法更改。首先,这是导致我麻烦的结构:
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
union{
struct {
u16 field_6;
} default_item_default_attacks;
struct {
u16 moves[4];
u16 field_E;
} default_item_custom_attacks;
struct {
u16 item;
} custom_item_default_attacks;
struct {
u16 item;
u16 moves[4];
} custom_item_custom_attacks;
} item_and_moves;
} trainer_pokemon;
正如您所看到的,结构trainer_pokemon
的大小取决于我使用哪个uninion成员进行实例化。问题是我需要实现几个trainer_pokemon[]
。正如预期的那样,我的C-Compiler只是将这个数组的每个成员的大小扩展到最大值(好像我总是使用工会成员custom_item_custom_attacks
进行实例化)。然而,我正在逆向工程的游戏期望阵列的成员匹配所使用的联合的大小。这可能听起来有些令人困惑,所以我将提供一个更具体的例子:
trainer_pokemon[] t = {
{
0x0, //build
0x0, //ability bit
false, //hidden ability
false, //shiny
},
0x0, //field_1
8, //Level
0, //field_3
POKEMON_LICHTEL, {
.default_item_default_attacks = {
0x0, //field_6,
}
}
},
{
{
0x0, //build
0x0, //ability bit
false, //hidden ability
false, //shiny
},
0x0, //field_1
6, //Level
0, //field_3
POKEMON_TRAUMATO,
{
.default_item_default_attacks = {
0x0, //field_6,
}
}
}
};
正如您所看到的,此数组的每个元素的8个字节足以实现此数组(总大小为16个字节)。但是,每个成员都填充为零,大小为16个字节(总大小为32个字节),因为编译器只假设我使用custom_item_custom_attacks
实例化,这需要额外的8个字节。问题是游戏引擎期望结构适合最小尺寸(在这种情况下为8个字节)。
如何最好地重新安装或修复此问题?另请注意,在一个数组中,所有成员都具有相同的大小,并且必须使用相同的联合成员进行实例化。
答案 0 :(得分:0)
听起来你所追求的是某种多态性(sp?)。您可以定义类似于
的结构,而不是使用联合struct base_type
{
int type;
};
struct type_a
{
struct base_type base;
long some_value;
};
struct type_b
{
struct base_type base;
char tiny_value;
};
struct base_type *my_type_a=malloc(sizeof(struct type_a));
my_type_a.type=1;
struct base_type *my_type_b=malloc(sizeof(struct type_b));
my_type_b.type=2;
struct type_a *a=(struct type_a *) my_type_a;
“type”结构体共享与base_type结构提供的相同的公共属性,但它们可以根据需要具有不同的大小。您只需要确保在分配内存时填充正确的值,以便能够正确识别它是哪个实际结构。
答案 1 :(得分:0)
您可以使用多个结构和基础结构:
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
} trainer_pokemon_base;
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
u16 field_6;
} trainer_pokemon_did;
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
u16 moves[4];
u16 field_E;
} trainer_pokemon_dic;
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
u16 item;
} trainer_pokemon_cid;
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
u16 item;
u16 moves[4];
} trainer_pokemon_cic;
答案 2 :(得分:0)
我会使用几种不同的结构类型:
typedef struct {
build_field build;
u8 field_1;
u8 level;
u8 field_3;
u16 species;
} trainer_base;
typedef struct {
trainer_base b;
u16 field_6;
} trainer_pokemon_default_item_default_attacks;
typedef struct {
trainer_base b;
u16 moves[4];
u16 field_E;
} trainer_pokemon_default_item_custom_attacks;
typedef struct {
trainer_base b;
u16 item;
} trainer_pokemon_custom_item_default_attacks;
typedef struct {
trainer_base b;
u16 item;
u16 moves[4];
} trainer_pokemon_custom_item_custom_attacks;
您还可以定义一个可以“成为”任何类型的自定义类型,以及您可以在trainer->extra_field[i]
访问额外字段的位置:
typedef struct {
trainer_base b;
u16 extra_field[0];
} trainer_pokemon;
您可以使用这样的自定义类型:
trainer_pokemon *trainer = malloc(sizeof(trainer_pokemon_default_item_custom_attacks));
trainer->extra_field[2]; // This would access moves[2].
trainer->extra_field[4]; // This would access field_E.
注意:使用sizeof
和数组运算时需要特别小心。您始终需要使用正确的特定类型。
注意:非常重要!如果您使用自定义类型和其他类型混合,那么您需要非常了解严格别名规则及其含义。如果您不熟悉严格的别名规则,则应坚持使用特定类型。