2016-11-27 6 views
0
int main() { 
    char src[] = "santosh"; 
    char dest[0]; 
    strncpy(dest, src, 4); 
    printf("%s\n", dest); // expecting o/p "sant" but o/p was "santtosh" 
    int i = 0; 
    while (dest[i]) { 
     printf("%c", dest[i]); //expecting output "sant" but it was "santtosh" 
     i++; 
    } 

    printf("\n"); 
    i = 0; 

    while (src[i]) { 
     printf("%c", src[i]); // expecting o/p "santosh" but it was "anttosh" 
     i++; 
    } 
    return 0; 
} 

이 코드에 문제가 있습니다. gcc 컴파일러를 사용하여 코드를 실행하고 여기에 출력이 있습니다 (주석 섹션). 왜 행동은 기대에 못 미치는가? 왜 strncpy()는 dest buff가 충분하지 않더라도 소스 문자열을 복사 할 수 있습니까?목적지 버퍼가 0 인 경우에도 strncpy가 소스 문자열을 복사 할 수있는 이유는 무엇입니까?

+5

'숯불의 최종 도착 [0]'<- 거의 전체 프로그램이이 시점에서 정의되지 않은 동작입니다. 그 선언으로 말하는 것은'dest' 배열은 0 문자의 * 고정 * 크기입니다. 따라서 아무 것도 포함 할 수 없으며 모든 액세스 (읽기 또는 쓰기)가 정의되지 않습니다. –

+2

영국 팝 밴드 ** UB40 **의 이름을 따서 명명되었습니다. 'C++'태그를 제거하는 것도 고려해야합니다. –

+1

정의되지 않은 동작입니다. C는 당신이 원하는 곳 어디에서든지 쓸 수있게 해줄 것이며, 당신이 해야할지를 결정하는 것은 당신에게 달린 것입니다 ... – Charles

답변

1

코드가 정의되지 않은 동작을 호출하여 일부 출력을 생성하는 이유 또는 다른 출력이 무의미하다는 것을 설명하려고 시도합니다. 당신은 <stdio.h>,도 <string.h>에 포함되지 않습니다

  • :

    는 여기에 문제가 있습니다. 이전에 정의되지 않은 함수 호출은 OK가 아닙니다. 정의되지 않은 동작을 방지하려면 적절한 헤더 파일을 포함하십시오.

  • char dest[0];0 크기의 배열을 정의합니다. 이러한 객체는 액세스 할 수 없으며 주소가 의미있는 것이 아니어도 액세스 할 수 없습니다. gccclang이 허용하지만 C 표준을 확장 한 것입니다. 이 정의는 오타처럼 보이지만, 바보 같은 버그를 방지하는 유용한 경고를하려면 gcc -Wall -W 또는 clang -Weverything을 사용하십시오.

  • strncpy(dest, src, 4);dest 길이가 4보다 작기 때문에 정의되지 않은 동작을 호출합니다. 소스 문자열의 길이가 size 인수보다 크거나 같으면 strncpy이 null이 아니므로 의 길이가 4 인 경우 동작은 여전히 ​​오류가 발생합니다. 여기 "santosh"의 길이는 7이므로 dest 문자는 s, a, nt이지만 null 종결자는 사용할 수 없습니다. while 루프는 while (dest[i])이 크기를 초과하여 dest에 액세스하므로 정의되지 않은 동작을 호출합니다. strncpy()은 오류가 발생하기 쉽기 때문에 그 의미가 널리 이해되지 않고 버그가 발생하기 쉽습니다. 이 기능을 사용하지 마십시오.

  • 으로는 현재 정의 또는이 char dest[4];로 정의 된 경우에도 같은 dest가 역 참조 할 수 없기 때문에 while (dest[i])가 정의되지 않은 동작을 호출, 위에서 설명했다.

여기 snprintf()strncat()를 사용하여, 개선 된 버전입니다 :

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

int main(void) { 
    char src[] = "santosh"; 
    char dest[5]; 

    *dest = '\0'; 
    strncat(dest, src, 4); 
    printf("%s\n", dest);  // will output "sant" 
    for (int i = 0; dest[i]; i++) { 
     printf("%c", dest[i]); // will output "sant" too 
    } 
    printf("\n"); 

    snprintf(dest, sizeof dest, "%s", src); 
    printf("%s\n", dest);  // will output "sant" 
    for (int i = 0; dest[i]; i++) { 
     printf("%c", dest[i]); // will output "sant" again 
    } 
    printf("\n"); 

    for (int i = 0; src[i]; i++) { 
     printf("%c", src[i]); // will output "santosh" 
    } 
    printf("\n"); 

    return 0; 
}