2010-01-29 6 views
0

나는 내 자신의 문자열 복사 기능을 쓰고 있습니다. 다음 작품 :C : 포인터가있는 물건에 논리가 없습니다.

char *src, *dest; 
src = (char *) malloc(BUFFSIZE); 
//Do something to fill the src 
dest = (char *) malloc(strlen(src) + 1); 
mystringcpy(src, dest); 

void mystringcopy(char *src, char *dest) { 
    for(; (*dest = *src) != '\0'; ++src, +dest); 
} 

그러나이 작동하지 않습니다

char *src, *dest; 
src = (char *) malloc(BUFFSIZE); 
//Do something to fill the src 
mystringcpy(src, strlen(src), dest); 

void mystringcopy(char *src, size_t length, char *dest) { 
    dest = (char *)malloc(length + 1); 
    for(; (*dest = *src) != '\0'; ++src, +dest); 
} 

하고 ... 실수 호출 된 함수 내에서 메모리를 할당 왜 내가 이해할 수 없다?

+3

'* src = (char *) malloc (BUFFSIZE);'앞에'*'를 써서는 안됩니다. – spoulson

+0

무엇이 오류입니까? 당신이 어딘가에 프로토 타입을 가지고 있지 않다면 mystringcopy는 아직 정의되지 않았다. –

+0

오, 그저 나에게 세분화 오류를주는 ... 두 번째로 다른 해결책을 확인해 보겠습니다 ... – Legend

답변

2

"작동하는"의미는 아직 말씀하지 않으 셨습니다. 그러나 dest이 호출 기능에서 새 메모리로 다시 변경되지 않는 이유를 혼동하는 것으로 가정하고 있습니다.

이유는 mystringcopy 함수에서 매개 변수 dest가 호출하는 함수의 포인터 dest사본 것입니다.

그런 다음 해당 복사본을 새 버퍼에 할당하고 복사본을 만든 다음 복사본이 사라집니다. 원본은 변경되지 않았습니다. dest을 포인터 (포인터)로 전달해야합니다.

또한 메모리에서 컴파일 한 내용을 컴파일해서는 안된다고 가정합니다 (호출 함수에서 잘못된 참조). 여기에 고정 된 코드는 다음과 같습니다 길이는 당신이 당신의 대상 버퍼 오버런 것 소스 버퍼의 실제 길이보다 작은 경우

char *src, *dest; 
src = (char *)malloc(BUFFSIZE); 

//Do something to fill the src 
dest = mystringcpy(src, strlen(src)); // assign dest 

char* mystringcopy(char *src, size_t length) { 
    char* dest = (char *)malloc(length + 1); 

    // for simplicity, make an auxiliary dest 
    char* destAux = dest; 

    for(; (*destAux = *src) != '\0'; ++src, ++destAux); 

    return dest; // give it back 
} 

가 유의 사항 :

char *src, *dest; 
src = (char *)malloc(BUFFSIZE); // no dereference on src, it's a pointer 

//Do something to fill the src 
mystringcpy(src, strlen(src), &dest); // pass the address of dest 

// take a pointer to a char* 
void mystringcopy(char *src, size_t length, char **dest) { 
    // now you should dereference dest, to assign to 
    // the char* that was passed in 
    *dest = (char *)malloc(length + 1); 

    // for simplicity, make an auxiliary dest 
    char* destAux = *dest; 

    // and now the code is the same 
    for(; (*destAux = *src) != '\0'; ++src, ++destAux); 
} 

또 다른 방법은 dest 포인터를 반환하는 것입니다. 해결책은 솔루션에 대한 의견을 참조하십시오.

+0

위대한 설명 .. 정말 고마워요 ... 한 가지 다른 질문은 길이를 넘기지 않으면 호출 된 함수 내부에서 이것을 계산해야한다고 가정합니다. 이 권리 또는 strlen 여전히 호출 된 함수 내부에서 작동합니까? – Legend

+0

함수에서'strlen'을 사용할 수 있습니다. 나는 그것을 실제로 내버려 둘 것이다. 예를 들어, 문자열의 부분 사본을 만들거나 하위 문자열을 추출 할 수 있습니다. – GManNickG

+0

오 ... 이해했습니다 ... 다시 한번 감사드립니다 ... – Legend

2

함수 내부의 할당에는 문제가 없습니다.

문제는 C에서 인수가 값으로 전달된다는 것입니다. 따라서 dest에 값을 할당하면 함수의 로컬 인 dest 만 수정됩니다.

두 가지 선택 사항이 있습니다. 당신은 이명 령 포인터를 반환 할 수 있습니다

char *alloc_and_copy(const char *src, size_t length) 
{ 
    char *dest = malloc(length + 1); 
    ... do your copying 
    return dest; 
} 

를하거나 지적되고 있는지 인수에 대한 포인터를 전달하고 수정할 수 있습니다 로컬 변수를 사용하는 기술이 필요하지 않습니다

void alloc_and_copy(const char *src, size_t length, char **dest) 
{ 
    char *local_dest = malloc(length + 1); 
    ... do your copying using local_dest 

    *dest = local_dest; 
} 

,하지만 난 더 읽기 쉬운 코드라고 생각합니다.

+0

문자열을 처리하려면 local_dest를 수정하기 전에 * dest를 할당하십시오. – jmucchiello

+0

@jmucchiello - 아이디어는 local_dest를 사용하여 함수의 모든 것을 수행하고 끝에 복사 만합니다 (그렇지 않으면 작은 값이 추가됩니다). 더 명확하게하기 위해 내 의견을 명확히했습니다. –

2

함수 내에서 malloc을 수행하는 것은 괜찮지 만 함수에서 포인터를 다시 전달하지는 않습니다. 어느 포인터 반환 :

char * mystringcopy(char *src) 

또는 포인터에 대한 포인터를 전달 : 일반적으로

void mystringcopy(char *src, char **dest) 
1

, 메모리를 할당 할 때 코드가 끝나면 메모리를 해제 할 책임이 무엇인지에 대한 특정 가정이 있습니다. 블랙 박스처럼 하나의 주요 연산에 대해 함수가 책임을 져야한다는 개념에 동의합니다. 두 가지 이유로, 자신의 메모리를 할당하고 버퍼를 채우는 함수에 포인터를 건네는 것이 가장 좋습니다.

그 외에도 char * 포인터를 반환 값으로 사용할 수 있습니다.

또는 char *dest 매개 변수를 char **dest으로 변경하십시오. 그런 다음 mystringcopy(src, strlen(src), *dest)과 같은 함수를 호출하십시오. 그리고 함수에서 포인터를 반환합니다 : *dest = (char *)malloc(length + 1);. 예쁘지 않은.

2

C의 매개 변수가 값에 의해 전달되므로 함수가 dest 포인터의 복사본을 가져오고 malloc으로 덮어 쓰고이를 버립니다. 이것을 다음과 같이 시도해보십시오 :

void mystringcopy(char *src, size_t length, char **dest) { 
    *dest = (char *)malloc(length + 1); 
    char *p=*dest; 
    for(; (*p = *src) != '\0'; ++src, ++p); 
} 

이제 포인터를 포인터로 전달하여 주 프로 시저에서 덮어 쓸 수 있습니다.

char *src, *dest; 
*src = (char *) malloc(BUFFSIZE); 
//Do something to fill the src 
mystringcpy(src, strlen(src), &dest); 
// now in dest you have your copy