3

I'm trying to create an array of strings inside a struct which represents a player's inventory.

I create a struct for the player:

typedef struct Player {
    char *inventory[];
} Player;

And then I use a function which allocates heap memory and creates (not sure if "create" is the right word here) the struct with some "items" inside the player's "inventory".

Player *spawnPlayer(void)
{
    Player *stats = malloc(sizeof(Player));

    stats->inventory[] = {"potion", "potion", "ether"};

    return stats;
}

Now I can create a normal array like this outside of a struct, but if I attempt to use the above, I get the below error while trying to compile:

arrays.c: In function 'spawnPlayer':
arrays.c:13:19: error: expected expression before ']' token
  stats->inventory[] = {"potion", "potion", "ether"};

Would someone be able to point me in the right path as to why this doesn't work?

3
  • That error message does not correspond to the code you've shown. Please fix one or the other. Commented Mar 6, 2016 at 19:53
  • My apologies about that! I fixed the error. The name was different in my test code and I had tried specifying a number inside of the brackets.. I changed it to reflect what I had pasted in the post and tried to compile. Commented Mar 6, 2016 at 19:56
  • Is it even legal to have an array inside a struct with unknown size, apart from for the variable-sized array trick? Commented Mar 6, 2016 at 20:04

3 Answers 3

6

Your definition of Player is an example of a C99 extension call flexible array: an array of unknown size that is the last member of a structure and that will be accessible only upto the size actually allocated for each instance. You probably did not mean to use that. And you cannot initialize the values with the syntax used in your spawnPlayer function.

You can define an array of fixed size this way:

typedef struct Player {
    char *inventory[3];
} Player;

And you can initialize an allocated instance of Player this way:

Player *spawnPlayer(void) {
    Player *stats = malloc(sizeof(*stats));

    stats->inventory[0] = "potion";
    stats->inventory[1] = "potion";
    stats->inventory[2] = "ether";

    return stats;
}

If you meant for the array to have a size known at runtime and use a flexible array, you probably want to add a member for the actual size allocated:

typedef struct Player {
    int size;
    char *inventory[];
} Player;

And you will allocate it and initialize it this way:

Player *spawnPlayer(void) {
    Player *stats = malloc(sizeof(*stats) + 3 * sizeof(*stats->inventory));

    stats->size = 3;
    stats->inventory[0] = "potion";
    stats->inventory[1] = "potion";
    stats->inventory[2] = "ether";

    return stats;
}

Flexible arrays are a C99 extension, you can simulate them in C90 by defining inventory with a size of 0 is the compiler supports it, or a size of 1, but it is not strictly portable.

There is a third possibility, using a pointer to an array of char*:

typedef struct Player {
    int size;
    char **inventory;
} Player;

Player *spawnPlayer(void) {
    Player *stats = malloc(sizeof(*stats));

    stats->size = 3;
    stats->inventory = malloc(sizeof(*stats->inventory) * 3);
    stats->inventory[0] = "potion";
    stats->inventory[1] = "potion";
    stats->inventory[2] = "ether";

    return stats;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the awesome explanation. I'll play around with this and implement it into my game.
1
typedef struct Player {
    char *inventory[10];
} Player;

static const char *arr[] = { "potion", "potion", "ether"};
memcpy(stats->inventory, arr, sizeof(arr));

Or

typedef struct Player {
    char **inventory;
} Player;

Player *stats = malloc(sizeof(Player));
stats->inventory = (char**)malloc(sizeof(char*) * 10);

static const char *arr[] = { "potion", "potion", "ether"};
memcpy(stats->inventory, arr, sizeof(arr));

Or

stats->inventory[0] = "potion";
stats->inventory[1] = "potion";
stats->inventory[2] = "ether";

Perhaps you should add a NULL pointer at the end to indicate the length.

stats->inventory[3] = NULL;

static const char *arr[] = { "potion", "potion", "ether", NULL };
memcpy(stats->inventory, arr, sizeof(arr));

Or simply have a int inventory_size in your struct.

1 Comment

In both cases you would also need to include some way of letting the user of a Player know that you have copied exactly three items into the list of 10
0

You need to explicitly declare an array called inventory specifying its size.

Then initialize a pointer to point to it.

This is the third time I've seen this mistake in two days.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.