结构初始化的C结构

克里斯多夫·卢斯

我对初始化复杂结构(结构的结构)的最佳方法有些困惑

我基本上有这样的设置

typedef struct {
    float x;
    float y;
} Vectorf;

typedef struct {
    Vectorf position;
    Vectorf direction;
    Vectorf velocity;
} Player;

初始化Player对象的最佳方法是什么?

变体A

Vectorf position = {1.0f, 1.0f};
Vectorf direction = {1.0f, 0.0f};
Vectorf velocity = {0.0f, 0.0f};

Player player = {position, direction, velocity};

变体B

Player *player = malloc(sizeof(Player));

player->position.x = 1.0f;
player->position.y = 1.0f;
player->direction.x = 1.0f;
player->direction.y = 0.0f;
player->velocity.x = 0.0f;
player->velocity.y = 0.0f;

--- Stuff ---

free(player);

甚至创建一个像

Player *createPlayer(float px, float py...)
Player createPlayer(float px, float py...)

但是我想在这些里面我又需要变体A或B。

这仅仅是口味问题还是两者都有好处?

我也有这样的东西

typedef struct {
    int x;
    int y;
    Texture *texture;
    bool walkable;
} Tile;

typedef struct {
    int width;
    int height;
    Tile *tiles;
} Map;

这里的create函数似乎更合理,因为我可以传递实际的地图数据。

巴勃罗

我认为答案应该取决于您的需求,两种创建对象的方式都可以。

有时,您只需要malloc使用对象几次就不需要担心分配内存,并且不需要在函数退出时让对象“存活”。因此,您的变体A就可以了。

有时您想要创建许多对象并将它们存储在其他数据结构(列表,树等)中,并且需要这些对象在整个程序中“存在”。在这种情况下,您的变体B会更好。AnT的答案向您展示了如何保存代码行以进行初始化。

我考虑使用的另一个时间malloc是当我知道该结构非常大并且将为每个对象消耗大量字节时,因此拥有大量字节可能会耗尽所有堆栈。在那种情况下,我宁愿将这些大对象放在堆中,并且使用指针进行处理要比调用不带指针的函数时创建副本要便宜得多。

malloc当将结构视为类并且希望使用干净的API创建,使用和销毁它们时,我也会使用我总是对函数使用前缀,对于每种对象类型,我总是具有create,init和free函数,如下所示:

typedef struct abc {
    // lot's of members
} Abc;

Abc *abc_create(void);
int abc_init(Abc *abc); // always with default values
void abc_free(Abc *abc);

int abc_do_A(Abc *abc, int x);
int abc_do_B(Abc *abc, int y);
....

第三个函数通常如下所示:

Abc *abc_create(void)
{
    Abc *abc = calloc(1, sizeof *abc);
    if(abc == NULL)
        return NULL;

    if(abc_init(abc) == 1)
        return abc;

    free(abc);
    return NULL;
}

int abc_init(Abc *abc)
{
    if(abc == NULL)
        return 0;

    // initializations
    ...

    return 1;
}

void abc_free(Abc *abc)
{
    if(abc == NULL)
        return;

    // do free of other malloced
    // members if present
    free(abc);
}

我认为这为您提供了非常清晰易用的API。我在工作时维护了一个C库,其中至少有50种以上这些结构,它们都具有相同的方案,使用它们很容易,因为它们的行为都像这样:

Abc *abc = abc_create(1, 2, 3);
if(abc == NULL)
{
    error handling
}

abc_do_A(abc, 12);
abc_do_A(abc, 11);
...
abc_free(abc); // when not needed anymore

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章