2016-11-03 3 views
-1

저는 C 언어를 천천히하지만 확실하게 배우고 있으며, 나는 이러한 결과물에 대해 혼란스러워합니다.문자 배열 조작

#include <stdio.h> 
#include <string.h> 


int main() { 

     mycat(5); 
     mycat(7); 
     mycat(30); 

     return 0; // from everything I've read this is necessary...? 

} 

char dest_buffer[100]; 
char str1[] = "Hello"; 
char str2[] = "World"; 

void mycat(int n) { 

    strcat(str1, str2); 
    memcpy(dest_buffer, str1, n); 
    printf("%s\n", dest_buffer); 

} 

다음은 내가 얻는 결과입니다.

마지막으로 지침에 따라 HelloWorld를 반환해야합니다. 나는 왜 그것이 단지 "orld"후에 계속 말하는지 완전히 확신하지 못한다. 이 문제를 해결하는 데 도움이되는 어떤 도움도 좋습니다! 나는 여기서 무엇을해야할지 너무 확신하지 못한다.

+4

할당되지 않은 메모리에 액세스하므로 UB이므로 컴파일러마다 다를 수 있습니다. –

+0

예를 들어'gcc'와'clang'을 사용하면 중단 된 호출이 발생합니다. 모든 컴파일러가이 작업을 수행하는 것은 아닙니다. –

+0

다른 사람이 귀하의 질문에 만족스럽게 대답 한 경우, 다른 사람들이 귀하를 위해 어떤 해결책을 찾았는지 알 수 있도록 허용 된 답변으로 표시하십시오. –

답변

0

프로그램이 이런 식으로 행동하는 이유를 이해하는 데 도움이되는 두 가지 방법이 있습니다. 먼저, C의 char 문자열은 일반적으로 null 바이트로 종료되므로 시작하려면 "Hello"는 실제로 6 바이트입니다. 둘째, 정적으로 할당 된 변수는 연속적인 메모리에 스택에 저장되므로 str1과 str2는 연속 12 바이트를 차지한다고 생각할 수 있습니다.

함수에서 strc2를 str2에서 str1로 복사하고 null 바이트부터 시작합니다. 첫 번째 호출 후에는 12 바이트가 "HelloWorld \ 0 \ 0"처럼 보입니다. 첫 번째 문자열에 null 바이트를 복사했기 때문에 strcat null이 출력을 종료했기 때문입니다. Str2는 여전히 "orld \ 0 \ 0"인 12 번째 바이트의 7 번째 바이트를 가리 킵니다. strcat에 대한 다음 호출은 문자열에 "orld"를 추가하여 "HelloWorldorld \ 0"을 제공합니다. 이 시점에서 str2는 "orldorld \ 0"을 가리키고 strcat에 대한 세 번째 호출은 그 바이트를 추가합니다.

그래서 memcpy를 호출하여 n 바이트를 복사하면 str1이 가리키는 문자열을 얻을 수 있습니다. 여기에서 중요한 점은 str2에 6 바이트를 정적으로 할당하고 코드가 할당 된 공간에서 메모리로 이동하여 스택의 다른 항목에서 사용하고 있다는 것입니다. 이것은 매우 나쁜 것이고, segfault에 묶여 있습니다.

1

무엇이 일어나고 있는지 더 잘 이해하려면 str1str2 어레이의 길이를 길이 100으로 변경하면 정의되지 않은 동작이 발생하지 않습니다.

@ 엘리 사도 프는 절대적으로 정확합니다. char str1[] = "Hello"과 같은 문자열을 정의하면 그 할당 된 메모리 덩어리는 크기가 6 바이트 (5 문자 + NULL 종결 자)가됩니다. 문자열을 strcat으로 연결할 때 대상 메모리가 충분한 지 확인해야합니다. https://www.freebsd.org/cgi/man.cgi?query=strcat&apropos=0&sektion=0&manpath=FreeBSD+10.3-RELEASE+and+Ports&arch=default&format=html

는의도 str1를 인쇄 우리의 printf 문에 레이블을 보자 : 여기에 당신이 도움이 될 수있는 strcat의 FreeBSD의 구현을위한 유용한 자원이다.

#include <stdio.h> 
#include <string.h> 

char dest_buffer[100]; 
char str1[100] = "Hello";     // changed to 100 
char str2[100] = "World";     // changed to 100 

void mycat(int n) { 
    strcat(str1, str2); 
    printf("str1 = %s\n, str1);   // added so you can see str1 
    memcpy(dest_buffer, str1, n); 
    printf("buffer = %s\n", dest_buffer); // labeled buffer printout 
} 

int main() { 
    mycat(5); 
    mycat(7); 
    mycat(30); 
    return 0; 
} 

출력 :

질문에
str1 = HelloWorld 
buffer = Hello 
str1 = HelloWorldWorld 
buffer = HelloWo 
str1 = HelloWorldWorldWorld 
buffer = HelloWorldWorldWorld 

왜 마지막 문자열이 World 3 회 말합니까? mycat을 호출 할 때마다메서드를 호출하면 str2/0 종결자가 str1의 끝에 str1의 첫 번째 /0부터 시작하기 때문입니다.

그래서 당신은 str1 당신이 mycat를 호출 한 다음은 n 바이트에 memcpy을, 항상 버퍼의 시작을 시작 할 때마다 추가 str2의 다른 사본을 가져 본다. 그래서 buffer을 인쇄 할 때 때로는 잘립니다.