结构初始化的C结构

标签 c struct reference initialization typedef

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

我基本上有这样的设置

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;

这里创建函数似乎更合理,因为我可以传递实际的 map 数据。

最佳答案

我认为答案应该是取决于您的需求,两种创建方式 对象没问题。

有时你不需要担心使用 malloc 分配内存,如果你 将只使用一个对象几次,你不需要 当函数退出时,对象“存活”。所以你的变体 A 就可以了。

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

我考虑使用 malloc 的另一次是 当我知道该结构非常大并且会消耗大量字节时 每个对象,所以有很多对象可能会吃掉你所有的堆栈。在 在那种情况下,我宁愿将这些大对象放在堆中,并且还要处理 使用指针比调用时必须创建副本便宜得多 不接受指针的函数。

当我将结构视为类并且我想要一个干净的 API 时,我也使用 malloc 创建、使用和销毁它们。我总是为函数使用前缀,我 每种对象类型总是有一个创建、初始化和自由函数,比如 像这样:

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

关于结构初始化的C结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48954628/

相关文章:

c - 如何对两个包含长数字的字符串进行加法?在C中

c - C 中的宏扩展——检索无符号 32 位字

python - ctypes.Structure 在运行时修改_fields_

c++ - 当类在 C++ 中被销毁时,引用属性是否被销毁?

c++ - 从函数交换并返回 Char 数组

java - 在凯撒密码中引用数组中的字符

c - GDB 远程调试在某些时候不会停止

c - C 中的用户提示

c - 如何检查 char 中是否存在 EOF?

c - 如何在运行时为结构数组赋值?