简体   繁体   中英

C can't print a string twice

I am doing a project where i must create a Black Jack simulation. So i started by creating a deck and a draw function. Since there are no strings in C i created two arrays of pointers to use them as a custom-string arrays. The thing is that when i print the card to see its value and suit ,only the first time it prints what expected. The second time is a mess. Can someone explain this to me ? Here is my code

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
char* suit[] = {"Diamonds", "Hearts", "Spades", "Clubs"};
char* facevalue[] = { "Seven", "Eight", "Nine", "Ten", "Jack","Queen", "King", "Ace"};
char* drawCard()
{
    char* card[50];
    int cardNumber=rand()%8;
    int cardColor=rand()%4;
    strcpy(card,facevalue[cardNumber]);
    char of[]=" of  ";
    char* xrwma =suit[cardColor];
    strncat(card,of,5);
    strncat(card,xrwma,8);
    return card;
}
int main()
{
    srand(time(NULL));
    char* c=drawCard();
    puts(c);
    puts(c);
    return 0;
}

The issue is that you are returning a pointer to an automatic array. Once the function returns, the array goes out of scope. Attempting to dereference the returned pointer results in undefined behaviour . The first call to puts() , while technically undefined, happens to work in your case. The second doesn't.

See Returning a pointer to an automatic variable for a discussion.

One solution is to allocate the array inside main() , pass a pointer to it (and its size) to drawCard() and let drawCard() populate it.

Variable card is a local array in function drawCard .

Being as such, it is allocated in the stack when function drawCard executes.

After function drawCard returns, you can no longer rely on the contents of this array.

Any succeeding operation may override that piece of memory at any time.

The fact that your program successfully prints it at the first call to puts , is nothing more than "a matter of luck" - the correct characters just happen to reside in the memory pointed by variable c , upon the first call to function fputs .

But since function fputs also uses the stack, that piece of memory is overridden soon thereafter, and by the time you call fputs again, the previous character values are no longer there.

BTW, looking at your usage of variable card , I get the feeling that you meant to declare it as char card[50] rather than char* card[50] .

Strictly speaking the problem is the lifetime of the automatic variable that drawCard() returns. It's only good for the one function call instance. C doesn't stop you from returning it but it's invariably not useful later.

And the reason for that is: the locals ( automatic storage class) are allocated on the stack. It's really fast; a single arithmetic op -- a subtract from the stack pointer -- can allocate every local in a function.

But when the call returns, the stack is adjusted back. At this point the next function call instance is going to reuse the same space. If you hang on to a reference into that space it will get trashed with superficially random and ever-changing stuff ...

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