2014-01-11 3 views
1

나는 블랙 잭 시뮬레이션을 만들어야하는 프로젝트를하고 있습니다. 그래서 저는 갑판과 무승부 기능을 만드는 것으로 시작했습니다. C에서 문자열이 없기 때문에 두 개의 포인터 배열을 만들어 사용자 지정 문자열 배열로 사용했습니다. 문제는 카드를 인쇄하여 가치와 소송을 볼 때 처음 예상 한 것을 인쇄 할 때뿐입니다. 두 번째는 엉망입니다. 누군가 나에게 이것을 설명 할 수 있습니까? 여기 내 코드가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; 
} 

답변

5

자동 배열에 대한 포인터를 반환한다는 것이 문제입니다. 함수가 반환되면 배열은 범위를 벗어납니다. 반환 된 포인터를 참조 해제하려고 시도하면 undefined behaviour이됩니다. puts()에 대한 첫 번째 전화는 기술적으로 정의되지 않았지만 귀하의 경우에 작동합니다. 두 번째는 그렇지 않습니다.

설명은 Returning a pointer to an automatic variable을 참조하십시오.

main() 안에 배열을 할당하고 그 포인터 (및 크기)를 drawCard()에 전달하고 drawCard()을 채우십시오.

+0

Thx 메이트, 작동했습니다 –

+0

또한 어떤 솔루션이 바람직합니까?'drawCard()'에 대한 포인터를 전달하거나 f.e.malloc을 사용합니까? 코드를보다 깨끗하게하기 위해서. Thx –

1

엄밀히 말하면 문제는 drawCard()이 반환하는 자동 변수의 수명입니다. 하나의 함수 호출 인스턴스에만 유용합니다. C가 반환하지 못하지만 나중에는 유용하지 않습니다.

그 이유는 다음과 같습니다. 로컬 (자동 저장 클래스)이 스택에 할당됩니다. 그것은 입니다. 실제로는입니다. 스택 포인터에서 빼는 단일 산술 연산 -은 함수의 모든 로컬을 할당 할 수 있습니다.

그러나 호출이 반환되면 스택이 다시 조정됩니다. 이 시점에서 다음 함수 호출 인스턴스는 동일한 공간을 재사용 할 것입니다. 그 공간에 대한 참고 자료에 매달려 있다면, 표면적으로 무작위로 끊임없이 변화하는 것들로 쓰레기를 버릴 것입니다 ...

2

변수 card은 기능이 로컬 배열 drawCard입니다.

그렇기 때문에 함수 drawCard이 실행될 때 스택에 할당됩니다.

함수 drawCard이 반환 된 후에는 더 이상이 배열의 내용에 의존 할 수 없습니다.

임의의 후속 작업은 언제든지 해당 메모리를 덮어 쓸 수 있습니다.

puts의 첫 번째 호출에서 프로그램이 성공적으로 인쇄한다는 사실은 "행운의 문제"에 지나지 않습니다. 올바른 문자는 변수 c을 가리키는 메모리에 상주합니다 기능 fputs.

그러나 함수 fputs도 스택을 사용하기 때문에 해당 메모리가 즉시 무시되고 fputs을 다시 호출 할 때 이전 문자 값은 더 이상 존재하지 않습니다.

현재 변수 card의 사용을 보면 char* card[50]이 아닌 char card[50]으로 선언하려는 느낌이 들게됩니다.

+0

+1'char * card [50]'에 +1. 이것은 컴파일러의 경고가 완전히 약화되지 않았 음을 의미합니다. 뭔가 OP가 고쳐 져야합니다. – chux

+0

그냥'char * card'라고 선언하면 괜찮습니까? –

+0

글쎄,'char * card = malloc (50 * sizeof (char))'또는'char card [50]'어느 것을 선호하든. 그냥 첫 번째 옵션을 선택하면 나중에 자유롭게 (...) 호출해야하고, 두 번째 옵션을 선택하면 함수 밖에서 사용할 수 없다는 점을 명심하십시오. –

관련 문제