0

I am trying to make a game of lives and this is the start of my code. The rest of my project is looking fine but I can't run it until I can properly assign memory to my struct "stack".

 typedef enum {
        CLUBS = 1,
        HEARTS,
        SPADES,
        DIAMONDS
    } cardsuit;

typedef enum {
    ACE_OF = 1,
    TWO_OF,
    THREE_OF,
    FOUR_OF,
    FIVE_OF,
    SIX_OF,
    SEVEN_OF,
    EIGHT_OF,
    NINE_OF,
    TEN_OF,
    JACK_OF,
    QUEEN_OF,
    KING_OF
} cardvalue;

typedef struct {
    enum cardsuit *suit;
    enum cardvalue *value;
} card;

typedef struct {
    int *size;
    int *index;
    int *indexOfPlay;
    card deck[];

} stack;

int main() {
    stack player1;
    stack player2;
    stack playStack;
    stack drawStack;
    int num = 1;
    int ds = 1;

    printf("Please enter the number of decks you wish to use:");
    scanf("%d", &num);
    ds = DECK*num;
    printf("\nYou have chosen to have %d decks, ie: %d cards.\n", num, ds);

    player1 = (stack *) malloc(sizeof (stack)*num);
    player2 = (stack *) malloc(sizeof (stack)*num); 
    player1.deck = malloc( sizeof(player1)*num);
    player2.deck = (card *) malloc(sizeof(card)*num);
    playStack = (stack *) malloc(sizeof (stack)*num);
    drawStack = (stack *) malloc(sizeof (stack)*num);
}

When I run my code like this I get an incompatible types in assignment for each of my malloc calls. My question is what is the correct way to assign memory to my struct stack?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

1 Answers1

0

Why on earth would you store pointers to enums in the card, rather than simple enum values? Likewise, why so many pointers in the stack? Apart from using radically more space than necessary (especially on a 64-bit system), it grotesquely complicates your life.

You're using the C99 'flexible array member' (FAM) construct; you have to initialize it correctly, and you are mismanaging that, too, I'm afraid. This code fixes the type declarations, and allows each player to have as many cards in their hand (stack) as there are cards in the number of decks they're playing with. Note how you simply add the space needed for the FAM to the size of the base structure. Note that you cannot sensibly use a structure with a FAM except with dynamically allocated space. When they are not dynamically allocated, the size of the array is always 0 and you cannot change the size of the array. You also cannot embed them into other structures or arrays (but you can have pointers to them in other structures or arrays).

#include <stdio.h>
#include <stdlib.h>

typedef enum
{
    CLUBS = 1,
    HEARTS,
    SPADES,
    DIAMONDS
} cardsuit;

typedef enum
{
    ACE_OF = 1,
    TWO_OF,
    THREE_OF,
    FOUR_OF,
    FIVE_OF,
    SIX_OF,
    SEVEN_OF,
    EIGHT_OF,
    NINE_OF,
    TEN_OF,
    JACK_OF,
    QUEEN_OF,
    KING_OF
} cardvalue;

typedef struct
{
    cardsuit  suit;
    cardvalue value;
} card;

typedef struct
{
    int size;
    int index;
    int indexOfPlay;
    card deck[];
} stack;

enum { DECK = 52 };

int main(void)
{
    stack *player1;
    stack *player2;
    stack *playStack;
    stack *drawStack;
    int num = 1;
    int ds = 1;

    printf("Please enter the number of decks you wish to use:");
    scanf("%d", &num);
    ds = DECK * num;
    printf("\nYou have chosen to have %d decks, ie: %d cards.\n", num, ds);

    player1   = (stack *) malloc(sizeof(stack) + sizeof(card) * ds);
    player2   = (stack *) malloc(sizeof(stack) + sizeof(card) * ds);
    playStack = (stack *) malloc(sizeof(stack) + sizeof(card) * ds);
    drawStack = (stack *) malloc(sizeof(stack) + sizeof(card) * ds);

    free(player1);
    free(player2);
    free(playStack);
    free(drawStack);
}

There are those who would excoriate you for the cast on malloc(), and they'll probably excoriate me for leaving the casts present. I don't agree with them, though there is no harm done when the cast is omitted. I do assume that you compile with stringent compilation options so there's no danger that you'd ever invoke malloc() without a function prototype in scope (i.e, you'd never omit #include <stdlib.h>). If you aren't that disciplined, then you aren't safe casting. Strict C99 requires the prototypes in effect.

I routinely compile with:

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror -c cards.c

The free() calls were added so the code did compile cleanly under those compilation options.

I didn't add code to check that the scanf() call succeeds; you can fix and should fix that.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278