我正在做一个我必须创建Black Jack模拟的项目。所以我开始创建一个套牌和一个绘图功能。由于C中没有字符串,我创建了两个指针数组,将它们用作自定义字符串数组。问题在于,当我打印卡片以查看其价值和适合时,只有它第一次打印出预期的内容。第二次是一团糟。谁可以给我解释一下这个 ?这是我的代码
#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;
}
答案 0 :(得分:5)
问题是您正在返回指向自动数组的指针。函数返回后,数组超出范围。尝试取消引用返回的指针会导致undefined behaviour。第一次调用puts()
,虽然技术上未定义,但恰好适用于您的情况。第二个没有。
请参阅Returning a pointer to an automatic variable进行讨论。
一种解决方案是在main()
内分配数组,将指向它的指针(及其大小)传递给drawCard()
,然后让drawCard()
填充它。
答案 1 :(得分:2)
变量card
是函数drawCard
中的本地数组。
因此,当函数drawCard
执行时,它被分配在堆栈中。
函数drawCard
返回后,您不能再依赖此数组的内容。
任何后续操作都可以随时覆盖该内存。
你的程序在第一次调用puts
时成功打印它的事实,只不过是“运气问题” - 正确的字符恰好存在于变量{{1}指向的内存中在第一次调用函数c
时。
但是由于函数fputs
也使用了堆栈,因此很快就会覆盖那段内存,当你再次调用fputs
时,之前的字符值就不再存在了。
BTW,看看您对变量fputs
的使用情况,我觉得您打算将其声明为card
而不是char card[50]
。
答案 2 :(得分:1)
严格地说,问题是drawCard()
返回的自动变量的生命周期。它只适用于一个函数调用实例。 C不会阻止你返回它,但它以后总是没用。
原因是:本地(自动存储类)在堆栈上分配。它真的快;单个算术运算 - 从堆栈指针中减去 - 可以分配函数中的每个局部。
但是当调用返回时,堆栈会被调整回来。此时, next 函数调用实例将重用相同的空间。如果你坚持参考那个空间,它会被表面随机和不断变化的东西所破坏......