1

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?

qwertyuiop
  • 33
  • 4
  • You need to allocate memory for player also. See this: https://stackoverflow.com/questions/2278933/nested-structures-allocating-memory – Shafi Dec 03 '17 at 04:52
  • Why not show an example of allocation code? Also note that hiding pointers behind `typedef` is generally a terrible practice. – ad absurdum Dec 03 '17 at 04:52
  • Possible duplicate of [nested structures allocating memory](https://stackoverflow.com/questions/2278933/nested-structures-allocating-memory) – Shafi Dec 03 '17 at 05:01
  • @DavidBowling just out of interest, why is it considered bad practice? And what should I do instead? – qwertyuiop Dec 03 '17 at 05:02
  • 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 Dec 03 '17 at 05:12
  • It hides the type from view. With `typedef struct _game *Game;` it is too easy to accidentally write something later like `Game *my_game = malloc(sizeof (Game));`, intending to allocate for a `struct`, but instead allocating for a pointer. It is generally bad to overuse `typedef`. Don't use just to save typing; instead use `typedef` when it actually makes code more clear. – ad absurdum Dec 03 '17 at 05:13

2 Answers2

1

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?
Community
  • 1
  • 1
user2736738
  • 30,591
  • 5
  • 42
  • 56
  • Thank you for the insight. Out of curiosity why is it bad practice to hide pointers under typedef? Would a solution be to just not use typedef? I've read elsewhere that typedef can be problematic and is not encouraged. I am only accessing the game elements through interface (using functions). But is this still not the right way to do it? – qwertyuiop Dec 03 '17 at 05:13
  • @qwertyuiop.: Have you checked the two references given. You will get a detail explanaton there. Here you could have simply `typedef` the original structure and then when you need pointer to it just declare it without using the pointer as a typedef. That solves the problem. – user2736738 Dec 03 '17 at 05:14
  • @qwertyuiop.: I have modified the answer, You can see how you could have done it simply without creating a typedef for pointer. – user2736738 Dec 03 '17 at 05:19
  • `Game game = malloc(sizeof *game);` -- look how confusing this line of code is; this should serve as a good example for OP of why not to `typedef` pointers like this. @qwertyuiop -- note that `typedef` does have legitimate uses. One good use is for returning complicated types from functions. `typedef`ing part of a complicated return type (perhaps an array, for example) can simplify function prototypes significantly. – ad absurdum Dec 03 '17 at 05:22
  • 1
    @DavidBowling.: Yes hiding a pointer inside struct basically leads to erroneous (and not readable) code most of the time. Because you always need to derefence it to get the result, the code loses readability. And every time you open the code sometimes later. It takes some time before you relaize that it's pointer to a struct. You are right that OP should get an idea from this. – user2736738 Dec 03 '17 at 05:25
0

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;
}
sg7
  • 6,108
  • 2
  • 32
  • 40