1
votes

Can I just allocate memory for this struct without allocating memory for each individual item inside it (in C)?

    typedef struct _game {
        int grid[SIZE][SIZE];
        int array[10];
        Player player[MAX_PLAYERS];
        int currentPlayer;
    } game;

Where these are in a separate header file (and player is a struct implemented in the same file as the game):

    typedef struct _game *Game;
    typedef struct _player *Player;

I'm just wondering, when I create a new instance of a game, do I need to allocated memory (with calloc or malloc for exmaple) for each player in the game (4 players)? I thought that since I have an array of players (or pointers to players) in the game struct already (and this array size isn't changing) then I would only need to allocate memory for the game struct itself. Is this the case? How is memory allocation used? And specifically how is it used with structs? Do I need to allocated memory for all other items in the struct as well?

2
You need to allocate memory for player also. See this: stackoverflow.com/questions/2278933/… - Shafi
Why not show an example of allocation code? Also note that hiding pointers behind typedef is generally a terrible practice. - ad absurdum
Possible duplicate of nested structures allocating memory - Shafi
@DavidBowling just out of interest, why is it considered bad practice? And what should I do instead? - qwertyuiop
You can check the reading list provided in my answer to get the answer to why you shouldnt typedef pointer. Long story short , it is quite problematic when we want to use it with const qualifier. - user2736738

2 Answers

1
votes

Well the way the structures are designed, you do need to allocate individual players.

Solution-1

You will just do

Game game = malloc(sizeof *game);

Then you have MAX_PLAYER number of _Player pointer variables. So it would be like

  for(size_t  i = 0; i<MAXPLAYERS; i++)
      game->player[i]= malloc(sizeof *game->player[i]);

Hiding pointers under typedef is not encouraged. It is a bad practice. Also you need to check the return value of malloc() and free the dynamically allocated memory when done working with it.

What have you done?

Player player[MAX_PLAYERS]; is array of pointers not array of _player variables. Here that's why for each pointer variable you need to allocate some memory. So that you can store player data into them.


Solution-2

You could simply do this:

typedef struct _game {
    int grid[SIZE][SIZE];
    int array[10];
    Player player;
    int currentPlayer;
} game;

Then allocate 10 player variables memory and assign the value returned by malloc to player.

Game game = malloc(sizeof *game);
..
game->player = malloc(sizeof *game->player *MAX_PLAYERS);
..

Solution-3

typedef struct _game {
    int grid[SIZE][SIZE];
    int array[10];
    struct _player player[MAX_PLAYERS];
    int currentPlayer;
} game;

Then you don't need to allocate individually for players. It already has MAX_PLAYER number of struct _player variable inside it.


As you asked about the typedef you could have simply done it like this

typedef struct _game {
    int grid[SIZE][SIZE];
    int array[10];
    Player player[MAX_PLAYERS];
    int currentPlayer;
} game;

...
...
game *mygame = malloc(sizeof *mygame);

This serves the purpose - and saves you from typing struct ... and also it is more readable and understandable.

Reading list

  1. Is it a good idea to typedef pointers?
  2. Is typedef'ing a pointer type considered bad practice?
0
votes

Do I need to allocated memory for all other items in the struct as well?

No, all items inside the struct will get memory allocated automatically.

This is example of allocation which also clears struct memory:

#include <stdio.h>

#define SIZE 10
#define MAX_PLAYERS 20

   typedef struct _player {  
        char name[10];
        int i;
    } Player;


    typedef struct _game {
        int grid[SIZE][SIZE];
        int array[10];
        Player player[MAX_PLAYERS];
        int currentPlayer;
    } game;

int main()
{
   game *g = calloc(1, sizeof (game));

   return 0;
}