【问题标题】:nested structures and pointers嵌套结构和指针
【发布时间】:2012-09-23 13:53:28
【问题描述】:

我几乎每次跳回 C 项目时都会把它搞砸。尝试访问结构中的结构时出现段错误。假设我有以下(简化的)游戏结构:

struct vector {
    float x;
    float y;
};

struct ship {
    struct vector *position;
};

struct game {
    struct ship *ship;
} game;

还有一个初始化飞船的函数:

static void
create_ship(struct ship *ship)
{
    ship = malloc(sizeof(struct ship));
    ship->position = malloc(sizeof(struct vector));
    ship->position->x = 10.0;
}

然后在main()中向下:

int main() {
    create_ship(game.ship);
    printf("%f\n", game.ship->position->x); // <-- SEGFAULT
}

【问题讨论】:

  • 作为旁注,您可以使用typedef struct {float x; float y;} vector; 之类的内容,因此您不必每次使用该类型时都说struct。

标签: c pointers structure


【解决方案1】:

您正在通过值传递game.ship,因此在create_ship 内部,变量ship 只是该指针的副本,它只是更改了副本。当函数返回时,指向你malloced 的指针会丢失,并且函数的效果在它之外不可见,除了内存泄漏。

您需要将指针传递给指针并通过它修改game.ship:

static void
create_ship(struct ship **ship)
{
    *ship = malloc(sizeof(struct ship));
    (*ship)->position = malloc(sizeof(struct vector));
    (*ship)->position->x = 10.0;
}

和

create_ship(&game.ship);

或者也许更好的方法是按照 Johnny Mopp 在 cmets 中的建议,从函数返回指针,而不是在函数外部修改指针:

static struct ship* create_ship()
{
    struct ship* s = malloc(sizeof(struct ship));
    s->position = malloc(sizeof(struct vector));
    s->position->x = 10.0;

    return s;
}

和

game.ship = create_ship();

当然,你有什么malloced,别忘了free。

【讨论】:

  • 或运送 * create_ship() { ... }
  • 没错,通往罗马的道路不止一条。
  • @JohnnyMopp 谢谢,我想让 OP 知道它为什么不起作用,但我添加了一些关于你的建议的内容。
【解决方案2】:

你应该通过引用传递:

static void create_ship(struct ship **ship);

和

create_ship(&game.ship);

否则分配的结构将被丢弃。

【讨论】:

    【解决方案3】:

    您的create_ship 函数实际上并没有改变game.ship,因为参数是按值传递。在create_ship 函数中,只有一个copy 被更改。所以在调用之后,game.ship 保持未初始化(或NULL,或调用之前的任何值)。因此,您也会丢失对新分配的船的引用,并泄漏内存。

    您需要将指针传递给指针才能更改它:

    static void create_ship(struct ship **ship)
    {
        *ship = malloc(sizeof(struct ship));
        // ...
    

    在通话中:create_ship(&amp;game.ship);

    您也可以选择将新船作为函数返回值传递出去:

    static ship *create_ship()
    {
        struct ship *ship = malloc(sizeof(struct ship));
        // ...
    
        return ship;
    }
    
    // ...
    
    game.ship = create_ship();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多