2009-10-15 3 views
2

C 문자열 문제로 나를 도울 수 있는지 궁금 해서요. 나는 3 char 포인터를 보내는 함수가있다. 이 함수 내에서 char 포인터는 올바르게 이동 및 수정됩니다. 그러나, 그들이 호출되는 주 함수로 돌아 가면 함수는 변경되지 않습니다. 나는 가치있게 지나가는 것이 실수인가?C에서 문자 포인터를 전달하고 수정하는 데 혼란이 있음 (참조 대 값)

int main(void) 
{ 
    LPSTR path = (char*)malloc(strlen(START_PATH)); 

    strcpy(path, START_PATH); 

    char* newstr = (char*)malloc(PATH_SIZE); 

    TrimVal(path, "*.*", newstr); 

    //Do Stuff 

    return 0; 
} 

void TrimVal(char* modify, char* string, char* newstr) 
{ 
     newstr[0] = '\0'; 

     modify = strncat(newstr, modify, (strlen(modify) - strlen(string))); 

     return; 
}  

참고 :PATH_SIZE 가정 크기 값되며, START_PATH 당신은을 수정이

modify = strncat(newstr, modify, (strlen(modify) - strlen(string))); 

일에서 char 배열

+0

@sgm : 여기 표준에 대한 아무것도. 아마도 당신은 Windows 데이터 유형의 사용에 의해 실망한 것입니까? –

+0

main()의 처음 두 줄은 자신이 생각하는대로하지 않는다는 것을 지적해야합니다. 첫째, sizeof (START_PATH)는 실제로 sizeof (char *)를 반환합니다. sizeof (variable)는 실제로 변수 _type_의 크기를 반환하기 때문입니다. 첫 번째 줄에서 sizeof를 strlen으로 바꾸려고합니다. 둘째, path = START_PATH를 쓸 때 START_PATH에 대한 포인터로 할당 한 메모리에 대한 포인터를 덮어 씁니다. 단순히 포인터를 복사하는 대신 strcpy를 사용해야합니다. –

+0

게시물에 소스를 수정했습니다. –

답변

6

여기 내 코드의 예입니다 포인터가 아닌 포인터.

path을 TrimVal에 전달할 때. 메모리 위치는 path입니다. 0x12345

modify = 할 때 로컬 변수 modify을 새 메모리 위치 (예 : 0)로 변경하십시오. 0x54321

main으로 돌아 가면 0x12345에 대한 포인터 만 있으며, 보이는 경우 아무 것도 변경되지 않았습니다.

당신이 당신의 숯불 * 변수가 함수에서 수정 될 것으로 예상되는 경우 쉽게

{ 
... 
TrimVal(&path, "*.*", newstr); 
... 
} 

void TrimVal(char** modify, char* string, char* newstr) 
{ 

     newstr[0] = '\0'; 

     *modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string))); 

     return; 

}  
+0

당신은 나를 때려 눕혔습니다.공정하지 않음 : P – wheaties

+0

은 이어야합니다. * modify = strncat (newstr, * modify, (strlen (* modify) - strlen (string))); –

+0

'TrimVal()'을 호출하는 코드를 변경하지 않고 이러한 변경을 수행하면'path'에 있던 포인터가 손실되고 힙에서 할당 된 메모리 누수가 발생합니다. –

0

을 수행하여 문제를 해결할 수 및 참조로 전달하려면, 당신은 문자 * 로 전달해야합니다. 당신이 참조로 포인터을 통과, 그래서 간접의 추가 계층이있을 필요가있다 기억 (통과 문자은 참조로 뭔가를 통과하지! - 단일 문자를)

0

C는 정말 통과 -이 없습니다 참조로. 여기서 뭘하는지 포인터 값으로 전달합니다. C의 문자열은 char에 대한 포인터로 나타냅니다. 따라서 함수 에서 TrimVal을 사용하면 포인터 자체가 아닌 문자열의 내용 (즉, 지시 된 데이터)을 수정할 수 있습니다.

strncat은 첫 번째 매개 변수의 내용을 수정하고 동일한 값을 반환합니다.

당신이 TrimVal경로의 값을 변경하려면

, 당신과 같이, 포인터에 대한 포인터를 전달해야합니다

... 

TrimVal(path, "*.*", newstr); 

... 

void TrimVal(char** modify, char* string, char* newstr) 

{ 
    newstr[0] = '\0'; 
    *modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string))); 
    return; 
} 
+1

은 * modify = strncat (newstr, * modify, (strlen (* modify) - strlen (string))))이어야합니다. –

+0

잘자요. 코드에서 수정되었습니다. –

1
void TrimVal(char* modify, char* string, char* newstr) 

modify, string의 값을 변경, 또는 함수 내에서 TrimVal() 함수는 호출 함수의 변수에 영향을 미치지 않습니다.

TrimVal() 함수 내부 modify, string 또는 newstr의 내용 변경 호출 함수의 변수에 반영 될 것이다.

그래서
void TrimVal(char* modify, char* string, char* newstr) 
{ 
    newstr[0] = '\0'; /* will be reflected in the calling function */ 
    modify = "a new string"; /* won't be reflected */ 
} 

나는 코드의 작은 청소와 기능, 당신이 원하는 것을 할 수 있다고 생각.

오 ... 그리고 path 변수가있는 메모리 누수가 있습니다. 공간을 malloc하고 그 후에 즉시 path 변수에 다른 값을 할당하여 해당 공간의 주소를 잃게됩니다.

0

처음 두 문장에 문제가 있습니다. 경로를 포인터 char로 선언하고이 주소 소유자에 저장된 메모리를 할당합니다. 다음 문장에서 경로의 값을 문자 배열 START_PATH의 시작으로 변경합니다. 할당 한 메모리가 손실됩니다.

또한 strncat은 malloc을 연결하기 위해 호출하지 않습니다. 연결을 유지할만큼 충분히 큰 버퍼를 전달할 것으로 예상되며 이는 잠재적 인 보안 위험입니다 (버퍼 오버런).

1

이 스레드에서 제기 된 많은 다른 좋은 것들에 추가 점 몇 :이 C 인 경우

LPSTR path = (char*)malloc(strlen(START_PATH)); 

, 당신은 malloc의 반환 값을 캐스팅해서는 안된다. (C FAQ 7.7b를 참조하십시오 더 중요한

, strlen는 포함하지 않는 그 계산 그래서, 메모리가 path 포인트 \0을 종료하는 START_PATH 플러스 \0를 개최 메모리의 필요한 양의 한 문자 짧은하는 것이 :...

strcpy(path, START_PATH); 

메모리가 path가 가리키는 과거를 작성하여 정의되지 않은 동작을 호출한다. malloc이 C의 반환 유형을 주조의 스타일에 대한

0

그냥 하나의 코멘트 모든. 캐스팅 할 때 오류를 숨길 수 있습니다.

이것은 훨씬 좋은 스타일입니다.

stdlib.h를 포함하고 malloc을 유형 독립으로 설정하십시오. 이 도움이

char *ptr_char = NULL; 

ptr_char = malloc(sizeof(*ptr_char)); 

희망,

관련 문제