2017-04-12 53 views
0

我有一个有点不寻常的问题。由于我是逆向工程代码,因此我使用的数据结构(这很糟糕)无法更改。首先,这是导致我的麻烦,现在的结构:与不同大小的成员结合的数组

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成员。问题是我需要instanciate几个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个字节)。但是,由于编译器只是假定我需要一个额外的8字节的custom_item_custom_attacks,所以每个成员都被填充到16字节的大小(总大小为32字节)。问题在于游戏引擎期望结构符合最小尺寸(在这种情况下为8个字节)。 我如何最好地改造或修复这个问题?还请注意,在一个数组中,所有成员的大小相同,并且必须立即与同一个工会成员同步。

+0

'sizeof(trainer_pokemon)'将会增加你工会中最大的元素。如果这是你的意思。 – tilz0R

+0

而那就是我想要阻止的。我想我必须重新构建我的数据结构,但是怎么做呢?有没有更好的办法? – PfannkuchenXD

+0

如果您在侧面结构中使用指针,然后在此变量之外初始化数据,该怎么办?所以你的结构只是指向某个地方。如果它非空,你知道它有有效值,否则你忽略它。 – tilz0R

回答

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; 

由base_type结构这二者,“型”结构共享相同的共同属性,但根据需要也可以是不同的尺寸。您只需确保在分配内存时填充正确的值,以便能够正确识别它是哪个实际结构。

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; 
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和数组运算时需要特别注意。您始终需要使用正确的特定类型。

说明:非常重要!如果您使用自定义类型和其他类型混合,那么您需要非常了解严格的别名规则及其含义。如果你不知道严格的别名规则,你应该坚持使用特定的类型。

相关问题