2014-09-04 5 views
2

이 코드를 시험해 보았습니다! 어떻게 작동하는지 이해할 수 없습니다.함수에 char * 전달하는 방법?

 int main() 
    { 
     char *s1; 
     s1=malloc(sizeof(char)*20); 
     strcpy(s1,"main"); 
     printf("%s\n",s1); 
     func(s1); 
     printf("After call %s\n",s1); 
     return 0; 
     } 
     void func(char *s2) 
     { 
     //free(s2);<--------------(this is what I'm talking about) 
     s2=malloc(sizeof(char)*25); 
     strcpy(s2,"func"); 
     printf("fun---%s\n",s2); 
     } 

출력 :

 main 
    fun---func 
    After call main 

내가 어떻게 모든 일을 알고 싶어

 main 
    fun---func 
    After call main 

하지만 주석 라인 출력이

Outout입니다 추가) (FUNC의 경우

공장. 즉, s1char*입니다. 할당 후에는 메모리 덩어리를 가리 킵니다. C에서 모든 것은 가치에 의해 전달됩니다. 따라서 전달할 때 청크 메모리의 주소를 보유하는 (스택) main의 로컬 범위에 다른 변수가 생성됩니다 (즉, s1에이 값이 포함되어 있음).

  • 이제 우리는 다음 main()s1에 변화의 반사를 얻기의 기회가없는 할당합니다. s1은 절대로 변경되지 않습니다.
  • 하지만 무료라면 func()을 호출 한 후 printf()의 메인에 가비지 값을 가져와야합니다.

올바른 생각입니까? 그렇지 않다면 개념을 깨끗이하십시오. Windows에서 나는 당신에게 말한 것처럼 결과를 주었다. 그러나 리눅스에서 그것은 어떻게해서든지 그 변화를 반영했다.

무엇이 누락 되었습니까?

답변

5

당신은 (대부분) 정확합니다. 다음으로 돌아 main()s1을 사용하여 함수 s2 (따라서 s1)을 확보

는 정의되지 않은 동작으로 알려진 것입니다.

무엇이든이 허용되도록 표준을 설정해야하기 때문에 안됩니다. 여기에 "모든 것"에는 작동 할 가능성이 포함되어 있습니다.

입니다. 아무도 그 메모리 블록을 다시 할당하고 데이터를 덮어 쓰지 않았기 때문에 거의 확실합니다. 따라서 여전히 원래 있던 내용이 포함되어 있습니다. func()에 대한 호출과 s1의 인쇄 사이 main()

하는 경우는, 당신은 삽입 : 다음

char *s3 = malloc(10000); 
strcpy (s3, "Yoohoo, I'v changed"); 

당신이 할 수있다 s1를 인쇄하는 당신에게 다른 결과를 줄 것이다 찾을 수 있습니다.

또는,이 UB를, 이후 아마 :-)

작동하는 것 같다 경우에도 정의되지 않은 문제가 발생하지 않도록하는 것이 바람직합니다. 컴파일러, 컴파일러 플래그 또는 코드 순서를 변경하거나 파란색 달에서 컴파일하는 경우 코드가 예기치 않게 작동하는 방식이 변경 될 수 있습니다.당신은 (단지 return를 사용하여) 이외의 다른 기능에 할당 된 포인터를 다시 전달하려면


, 당신은 이중 간접 사용할 수 있습니다 : 이것은 당신이 어떻게

void allocStr (char **pStr) { 
    free (*pStr); 
    *pStr = malloc (1000); 
} 
: 
char *xyzzy = NULL; 
allocStr (&xyzzy); 

을 통과 부산물 C.

+0

감사! 이제 func에 line()을 추가하지 않고 메모리 누수가 있으면 할당합니다. 그러나 함수에 char * 만 전달하고 호출 함수의 변경을 반영하는 메모리를 할당하여 할당 할 수있는 방법은 없습니다 isn 그것? – coderredoc

+0

@amalsom 함수에서 변경하고자하는 다른 값과 마찬가지로 포인터를 변경하려는 포인터를 전달해야합니다. –

+0

@ amalsom. 메모리를 할당하고 다시 전달하려면 _double_ indirection을 사용하고 대답을 업데이트합니다. – paxdiablo

3

참조 (이것은 귀하의 질문에 대답하지 않지만 코멘트에 넣어 훨씬에 있습니다.)

은 당신이 일 통과해야 undefined behavior없이 작동하게하려면 e 포인터 (또는 오히려 C에서 가능하지 않으므로 참조 의미에 따라 패스를 에뮬레이트해야합니다.) 이것은 포인터에 포인터를 전달하여 수행 할 수 있습니다. 그런 다음 함수에서 포인터를 변경할 수 있습니다.

void func(char **s2); // Pointer to pointer 

int main(void) 
{ 
    char *s1 = malloc(20); // No need for `sizeof` as `sizeof(char)` is always 1 
    strcpy(s1, "main"); 
    func(&s1); // Note use of `&` address-of operator 
} 

void func(char **s2) 
{ 
    free(*s2); // Note use of dereference operator `*` 
    *s2 = malloc(20); 
    strcpy(*s2, "func"); 
} 
+0

@ Joachim. 고마워요. 네! 당신은 변수 ** s1의 주소를 저장하는 char **를 사용하고 있습니다. 그래서 주소를 포함하는 임시 변수에 포함되어 있지만 실제 변수에서 발생하는 모든 변경 사항은 반영됩니다. func(). 고마워. 내 생각이 맞는지 말해봐. – coderredoc

0

당신이 말한대로 모든 일이 정확히 작동 같은

뭔가. 부실 포인터 (s2가 해제 된 메모리를 가리키는)를 역 참조 할 때 두 번째 실행에서 쓰레기를 얻지 못한 이유는 시스템이 아직 메모리를 다시 사용하지 않았기 때문입니다.

+0

고마워. 어제 내 linux m/c에서 실행했을 때 일어난 일이라고 생각한다. – coderredoc

관련 문제