2013-05-27 2 views
1

는 프로그램의 코드이다 : 경고는 표시 편집 후동적 및 정적 문자 배열 여기

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

char * cloning(char * q){ 
    char s[strlen(q)]; 
    int i; 
    for(i = 0; i < strlen(q); i++) 
     s[i] = q[i]; 
    return s; 
} 

int main(){ 
    char q[] = "hello"; 
    char *s = cloning(q); 
    return 0; 
} 

는, 그래서 이런 리턴 값 변경이 방법

char *b = s; 
return b; 

을 경고를 해결할 수 있습니다. 그러나 함수 cloning() 내 sizeof (s)는 5이지만 strlen (s)은 7이라는 사실을 발견했습니다. char s [strlen (q)]를 단순히 char s [5]로 변경하면 출력은 여전히 부정확하다. 아무도 나에게이 문제를 설명 할 수 있습니까? 고맙습니다.

+0

char * char_array; char_array = 새로운 문자 [150]; // delete [] char_array; char_array = NULL; – TomeeNS

답변

0

C의 동적 배열은 Malloc과 Calloc을 사용하여 선언됩니다. 인터넷 검색을 시도하십시오.

예 :

char *test; 

    test = (char *)malloc(sizeof(char)*Multiply_By); 
+0

맞습니까?하지만이 질문에 대한 답은 실제 질문입니까? – Wolf

6

char s[strlen(q)]는 지역 변수이며, 당신은 그것의 주소를 반환 할 때 따라서, 그것은 정의되지 않은 동작이 발생합니다. 따라서 strdup() 또는 malloc()을 사용하여 배열을 동적으로 할당 할 수 있으므로 함수에서 돌아 왔을 때 배열 s을 힙에서 사용할 수 있습니다. 반환되는 배열은 다른는 것, free()뿐만 아니라 -ed로 메모리 누수 :

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

char * cloning(char * q){ 
    char *s = malloc(strlen(q)+1); 
    // if you write char s[strlen(q)], it is defined locally, and thus on return gives an undefined behaviour 
    int i; 
    for(i = 0; i < strlen(q)+1; i++) 
     s[i] = q[i]; 
    return s; 
} 

int main(){ 
    char q[] = "hello"; 
    char *s = cloning(q); 
    free(s); 
    return 0; 
} 
+1

'char s [strlen (q)];는 유효한 C99 가변 길이 배열입니다. 정의되지 않은 동작이 아닙니다. 그러나 자동 저장 기간이 있기 때문에 * 무효 인 포인터는 포인터를 반환합니다. – icktoofay

+0

OP는 그가 C99에서 작동하는지 여부를 지정하지 않았으므로 말하기 위해 예술적 라이센스를 받았습니다 :) 그러나 감사합니다.나는 malloc() 배열을 해제하기 위해 해답을 편집했다. –

+0

우리가 C99보다는 C89를 사용한다고 가정한다면 VLA 사용은 * 컴파일 타임 오류 *가 될 것이다. 정의되지 않은 동작을 호출 할 기회가 생기기 전에 컴파일러에 의해 캐치됩니다. – icktoofay

3
char s[strlen(q)]; 

는 가변 길이 배열을해야합니다. malloc으로 묶인 버퍼와 마찬가지로 런타임에도 크기가 결정됩니다. malloc으로 묶인 버퍼와는 달리 함수가 반환 될 때 버퍼는 존재하지 않습니다.

-1

C에서는 정적 배열이 스택에 있고, 함수가 반환 된 후 destreeed되었습니다. char을 가진 string은 '\ 0'끝을 가진다. 그러나 strlen은 그것을 포함하지 않습니다. 예를 들어. 당신이 문자열을 복사하려면 char q[] = "hello"; strlen(q) = 5,but the real size is 6 , 마지막은 '\ 0'당신은 또한 MEM 누출 될 using.Maybe 후를 확보해야

char *s = malloc(sizeof(q)); ...; for(i = 0; i < sizeof(q); i++) s[i] = q[i];

사용하여 end.or에 추가해야합니다.

희망이 있으면 도움이 될 것입니다. 이 코드

+0

-1 : 'sizeof'가'4 '를 반환 할 것이기 때문에 Byd의 조언. 그냥 시도 해 봐! – Wolf

3

여러 문제 :

char * cloning(char * q){ 
    char s[strlen(q)]; // s has strlen size but needs strlen + 1 to hold \0 
    int i; 
    for(i = 0; i < strlen(q); i++) // should copy the \0 otherwise q is not a valid string 
     s[i] = q[i]; 
    return s;// returns the address of a local var == undef. behavior 
} 

당신이 문자열을 바로 할()에서는 StrDup

char* cloning(char* q) 
{ 
    return strdup(q); 
} 

또는 동등한

char * cloning(char * q) 
{ 
    char* s = malloc(strlen(q)+1); 
    int i; 
    for(i = 0; i < strlen(q)+1; i++) 
     s[i] = q[i]; 
    return s; 
} 
+0

실제로 '\ 0'을 고려할 필요가 없으므로 배열에 strlen (q) +1 공간을 할당 할 필요가 없습니다. char s []의 정의를 char * s = malloc (sizeof (char) * strlen (q))로 변경하면이 프로그램을 수정할 수 있습니다. 내 혼란은 char s [strlen (q)]를 char s [5]로 변경하면 결과가 달라진다는 것입니다. – CrazyHenry

+2

@CrazyHenry :'char s [strlen (q)];를'char s [5];로 바꾸는 것을 제외하고 기존 코드를 사용하면 자동 저장 기간을 가진 객체에 대한 포인터를 반환함으로써 정의되지 않은 동작이 발생하므로 유효하지 않습니다. 정의되지 않은 동작을 트리거하는 것이 일관 될 필요는 없습니다. – icktoofay

+1

@CrazyHenry s가 q와 동등한 문자열을 가리키고 싶다면, s는 q와 같은 장소에서' '\ 0'을 필요로합니다. – Sebivor

2

적절한 방법을 복제 할 경우 C 표준에 상관없이 표준 C를 사용하면 다음과 같이됩니다.

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

char* cloning (const char* str) 
{ 
    char* clone; 
    size_t size = strlen(str) + 1; 

    clone = malloc(size); 
    if(clone == NULL) 
    { 
    return NULL; 
    } 

    memcpy(clone, str, size); 

    return clone; 
} 

int main(){ 
    char original[] = "hello"; 
    char* clone = cloning(original); 

    if(clone == NULL) 
    { 
     puts("Heap allocation failed."); 
     return 0; 
    } 

    puts(clone); 

    free(clone); 
    return 0; 
} 
+0

+1하지만'puts (NULL)'은 어떨까요? – Wolf

+0

@Wolf 메인에서 에러 핸들링을 추가해야합니다 ... 편집하겠습니다. – Lundin