2017-04-12 52 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和數組運算時需要特別注意。您始終需要使用正確的特定類型。

說明:非常重要!如果您使用自定義類型和其他類型混合,那麼您需要非常瞭解嚴格的別名規則及其含義。如果你不知道嚴格的別名規則,你應該堅持使用特定的類型。

相關問題