总结我有两个结构,item
和player
,player
结构在其字段中包含两个item
结构。
item
结构有一个指向player
结构的指针的字段,该指针必须指向拥有此项目的玩家。
当我初始化玩家时new_player()
1}}我想让项目指向在函数中创建的player
。
对我来说,它似乎不可能,因为项目将指向在堆栈上创建的结构,一旦返回结构,其项目成员指向释放的内存。我做了一些似乎证实这个理论的测试。
代码:
struct item
{
int power;
struct player* owner;
};
struct item new_item(int power, struct player* owner)
{
struct item an_item;
an_item.power = power;
an_item.owner = owner;
return an_item;
}
struct player
{
int age;
struct item item_1;
struct item item_2;
};
struct player new_player(int age)
{
struct player a_player;
a_player.age = age;
a_player.item_1 = new_item(1, &a_player);
a_player.item_2 = new_item(2, &a_player);
return a_player;
}
对此的解决方案可能是返回指向player
new_player()
的指针并将其分配到堆上:
struct player* new_player(int age)
{
struct player* a_player = malloc(sizeof (struct player));
a_player->age = age;
a_player->item_1 = new_item(1, a_player);
a_player->item_2 = new_item(2, a_player);
return a_player;
}
试验:
int main()
{
struct player* player_1 = new_player(77);
printf("Age of the player: %d.\n", player_1->age);
printf("Age of the player (from item_1): %d.\n", player_1->item_1.owner->age);
printf("Age of the player (from item_2): %d.\n", player_1->item_2.owner->age);
printf("Age of the player (from item_1 by owner): %d.\n",
player_1->item_1.owner->item_1.owner->age);
printf("Age of the player (from item_2 by owner): %d.\n",
player_1->item_2.owner->item_2.owner->age);
printf("Age of the player (from item_1 by owner to item_2): %d.\n",
player_1->item_1.owner->item_2.owner->age);
printf("Age of the player (from item_2 by owner to item_1): %d.\n",
player_1->item_2.owner->item_1.owner->age);
printf("Power of the first item: %d, power of the second item: %d.\n",
player_1->item_1.power, player_1->item_2.power);
printf("Power of the first item (from item_1): %d, power of the first item (from item_2): %d.\n",
player_1->item_1.owner->item_1.power, player_1->item_2.owner->item_1.power);
printf("Power of the second item (from item_1): %d, power of the second item (from item_2): %d.\n",
player_1->item_1.owner->item_2.power, player_1->item_2.owner->item_2.power);
free(player_1);
return 0;
}
有些实验过的C程序员可以给我建议最好的方法是什么(或其他我想不到的方法)?
答案 0 :(得分:3)
在你拥有的玩家结构中,这些项目是玩家的一部分。因此,当您在堆上分配播放器时,您只需将项目内的播放器指针设置为新创建的播放器即可。
你是对的,如果你在堆栈上创建玩家,这将不起作用,因为在返回后,玩家对象将被复制,包括指向项目的指针(然后指向"之前的& #34;播放器在堆栈中的位置。
另一种经常使用的解决方案是将播放器分配到new_player函数之外并将其作为指针传递:
void new_item(struct item *i, int power, struct player *p) {
i->owner = p;
i->power = power;
}
void new_player(struct player *p, int age) {
p->age = age;
new_item(&p->item_1, 1, p);
new_item(&p->item_2, 2, p);
}
struct player p;
new_player(&p, 10);
这样,您可以将对象的分配与初始化分离。例如,你可以拥有一大堆玩家对象来容纳所有玩家并且只分配一次。然后通过将指针传递给数组中的对象来初始化播放器对象。
或者您可以堆积分配播放器并使用相同的功能初始化它。
答案 1 :(得分:1)
作为参考,专业的程序设计将涉及以下内容:
你最终会得到这样的东西:
item.h
#ifndef ITEM_H
#define ITEM_H
#include "player.h"
#include <stdlib.h>
typedef struct item_t item_t;
typedef struct player_t player_t; // forward declaration needed to prevent linker errors
item_t* item_create (int power, const player_t* owner);
void item_delete (item_t* item);
#endif
item.c
#include "item.h"
struct item_t
{
int power;
const player_t* owner;
};
item_t* item_create (int power, const player_t* owner)
{
item_t* new_item = malloc(sizeof(*new_item));
if(new_item != NULL)
{
new_item->power = power;
new_item->owner = owner;
}
return new_item;
}
void item_delete (item_t* item)
{
free(item);
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "item.h"
#include <stdlib.h>
typedef struct player_t player_t;
typedef struct item_t item_t; // forward declaration needed to prevent linker errors
player_t* player_create (int age);
void player_delete (player_t* player);
#endif
player.c
#include "player.h"
struct player_t
{
int age;
struct item_t* item_1;
struct item_t* item_2;
};
player_t* player_create (int age)
{
player_t* new_player = malloc(sizeof(*new_player));
if(new_player != NULL)
{
new_player->age = age;
new_player->item_1 = item_create(1, new_player);
new_player->item_2 = item_create(2, new_player);
}
return new_player;
}
void player_delete (player_t* player)
{
item_delete(player->item_1);
item_delete(player->item_2);
free(player);
}
答案 2 :(得分:0)
将相同的原则应用于new_item()
函数。它必须返回指向已分配结构的指针。
我想建议你提供另一个函数,它将负责释放所有这些指针。它可以是一个destroy_player(struct player *player)
,可以释放这两个项目和玩家本身。