简体   繁体   中英

Random value in struct field

I'm trying to learn some C and I've started with a simple deck of cards program.

The card is struct containing two ints for face and suit. And I'm building a deck by allocating 52 cards, and going thorough a loop.

card *Deck = (card*)malloc(sizeof(card) * 52);
for(int i = 0; i < 4; i++){
    for(int j = 1; j < 14; j++){
        Deck->face = j;
        Deck->suit = i;
        Deck += sizeof(card);
    }
}
Deck -= sizeof(card) * 52;
printDeck(Deck);

free(Deck);

I have a printCard function that takes a single pointer and prints the values, and a print deck function that calls printCard 52 times. If i print the cards as they are being created, everything goes well, but if i print the cards after all have been created for some reason I get a segfault at the 6th card. I fired up gdb and noticed this output:

Seven of Diamonds<br>
(null) of Diamonds<br>
Nine of Diamonds<br>

The rest of the output is normal. When checking for the value of the 6th card i got:

(gdb) p c->face
$10 = 2675

If i am skipping the 6th card the output is fine and everything works the way it should. I'm new to C but i can't really see how that value got put in that field in my code.

struct card{
    int face;
    int suit;
};

void printCard(card* c){
    printf("%s of %s\n", face_str[c->face], suit_str[c->suit]);
}

Edit:

The printDeck code:

Before:

void printDeck(card* c){
    for(int i = 0; i < 52; i++){
        printCard(c);
        c += sizeof(card);
    }
}

After:

void printDeck(card* c){
    for(int i = 0; i < 52; i++){
        printCard(c);
        c++;
    }
}

printCard didn't changed:

void printCard(card* c){
    printf("%s of %s\n", face_str[c->face], suit_str[c->suit]);
}

The problem in your code is this line:

Deck += sizeof(card);

Here, Deck is a card * (pointer to card ). If you want to advance of one position, pointer arithmetic does the job for you, and doing Deck + 1 already advances sizeof(card) ahead. Adding or subtracting from a pointer p always advances sizeof(*p) .

The correct code would be:

Deck += 1;
// or 
Deck++;

The same mistake is done after the loop, here:

Deck -= sizeof(card) * 52;

Which should be:

Deck -= 52;

I'm new to C but i can't really see how that value got put in that field in my code.

When you wrongly modify the variable Deck , you end up accessing memory that is beyond the size of the allocated chunk (which is sizeof(card) * 52 ). This is undefined behavior in C, and therefore trying to print such a value could result in random values being printed (if not worse).


I would suggest you to completely avoid modifying the value of Deck , and instead index it like an array:

card *Deck = malloc(sizeof(card) * 52);

for(int i = 0; i < 4; i++){
    for(int j = 1; j < 14; j++){
        Deck[i*13 + j]->face = j;
        Deck[i*13 + j]->suit = i;
    }
}

printDeck(Deck);
free(Deck);

It would be interesting to show us the code of the printDeck function.

The problem you have in the given code is Deck += sizeof(card) . You assumed that this would move Deck sizeof(card) bytes further. But that is not correct. When Deck is a pointer on card , incrementing Deck by one will increment its address by sizeof(card) bytes.

So your code should be

card *Deck = malloc(sizeof(card) * 52);
for(int i = 0; i < 4; i++){
    for(int j = 1; j < 14; j++){
        Deck->face = j;
        Deck->suit = i;
        Deck++;
    }
}
Deck -= 52;
printDeck(Deck);

free(Deck);

You might have made the same error in printDeck .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM