C语言 你能返回一个在函数内部声明的结构吗?

b5lpy0ml  于 2022-12-03  发布在  其他
关注(0)|答案(3)|浏览(187)

我想返回声明的结构体,以及在initializePlayer()函数中设置的值,这样我就可以在main函数中调用它。
这是一个任务,我们不允许声明全局变量(仅在函数内部),所以我认为我需要在函数内部声明struct-除非它不是一个变量(?)我真的不知道:(
这是我的代码,我无法让它工作

struct Player initializePlayer(int playerNumber)
{
    struct Player
    {
        int position[1][2];
        double money;
        int propertiesOwned[10];
    } player[4];

    // Set player's position to starting tile
    player[playerNumber].position[0][0] = 5;
    player[playerNumber].position[0][1] = 0;
    // Set player's default money
    player[playerNumber].money = 300000;
    // Set player's properties to none
    for (int i; i <= 10; i++)
    {
        player[playerNumber].propertiesOwned[i] = 0;
    }
    // Player initialized

    return player[playerNumber];
}

int main()
{
    // Initializes player 1 and 2
    struct Player p1 = initializePlayer(1);
    struct Player p2 = initializePlayer(2);
    return 0;
}

但是,如果我将struct声明为global,它就可以正常工作。
我希望函数返回一个结构体,该结构体在函数内部声明

trnvg8h3

trnvg8h31#

这是一个任务,不允许我们声明全局变量(仅在函数内部)
型别规范不是变数。
您需要在使用结构之前宣告它。
同样在函数定义中,返回类型应该是一个完整的对象类型。来自C标准(6.9.1函数定义)
3函数的返回类型应为void或除数组类型以外的完整对象类型。
所以这个函数定义

struct Player initializePlayer(int playerNumber)
{
    struct Player
    {
        int position[1][2];
        double money;
        int propertiesOwned[10];
    } player[4];
    //...

是错误的。函式的传回型别不是完整的对象型别。
您需要在函数定义之前定义结构,如

struct Player
    {
        int position[1][2];
        double money;
        int propertiesOwned[10];
    };

同样,最好通过指向结构类型的对象的指针,通过引用将该对象传递给函数。
在这种情况下,函数声明如下所示

void initializePlayer( struct Player *player )
{
    // Set player's position to starting tile
    player->position[0][0] = 5;
    player->position[0][1] = 0;
    // and so on

函数返回类型为void
并且结构类型的对象数组将在main中声明

int main( void )
{
    struct Player player[4] = { 0 };

    // Initializes player 1 and 2
    initializePlayer( &player[1] );
    initializePlayer( &player[2] );

    return 0;
}
0aydgbwb

0aydgbwb2#

是的,你可以返回一个结构体。你不能做的是返回一个指针,指向一个已经不存在的东西。但这不是你在这里要做的。结构体数据在这里被复制到调用者。
另一方面,你对那个结构体的定义很奇怪。它应该在任何使用之前完成。我不明白你为什么要把那个定义放在函数里面。
为了证明我的观点,举一个例子(使用不同的更简单的Player定义)

#include <stdio.h>

struct Player {
    int pos;
    char name[10];
};

struct Player f(){
    struct Player player;
    sprintf(player.name, "John");
    player.pos=12;
    printf("addr of f's local player: %p\n", &player);
    return player;
}

struct Player g(){
    struct Player player;
    player.pos=1;
    sprintf(player.name, "xxxxxxxxx");
    printf("addr of g's local player: %p\n", &player);
    return player;
}

int main(void) {

    struct Player p;
    p=f();
    struct Player q=g();
    printf("%s %d\n", p.name, p.pos);

  return 0;

在我的电脑上,它打印

addr of f's local player: 0x7ffec7aa8ae0
addr of g's local player: 0x7ffec7aa8ae0
John 12

这里的要点是,你可以看到,在main中,p.namep.pos实际上是在f中设置的。由于g已经在其间被调用,g在它的局部变量player中放入了其他内容,由于你可以看到(这不是一个确定的事情,但它是可以预测的,当我想证明我的观点时,它发生了)fg的局部变量player具有完全相同的地址,你知道,在我们得到f结果和我们打印它的时间之间,曾经在f的本地player中的内容已经被破坏。
尽管如此,我们还是把内容做对了。
因为f返回了其本地player的副本。
所以,是的,你可以返回struct。
这仍然是一个棘手的问题,因为如果该结构本身包含指向某些局部变量的指针,那么这些指针就不再有效。但是在您的用法中(一旦您更正了定义struct Player的位置,以及奇怪的[1]数组),就不会出现这样的问题。返回的是一个副本。

dwthyt8l

dwthyt8l3#

您尝试在struct player尚未定义之前使用它。您无法这样做,您需要在struct之前定义它。
你想这样,这是通常的,标准的和完全正确的方式:

// declare the struct (this does not declare a global variable)

struct Player
{
  int position[1][2];
  double money;
  int propertiesOwned[10];
};

// Now you can use it 
struct Player initializePlayer(int playerNumber)
{
  struct Player player[4];

还有另外一个问题:

for (int i; i <= 10; i++)

这是错误的,您忘记初始化i

for (int i = 0; i <= 10; i++)

其他地方可能有其他错误,我没有检查所有的东西。

相关问题