2014-01-25 4 views
3

내 원래 문제는 내가 두 값을 반환 할 수있는 함수를 작성하고 싶습니다. 두 인수의 주소를 함수에 전달하고 해당 함수 내에서 직접 값을 계산하여이 작업을 수행 할 수 있음을 알고 있습니다. 그러나 실험을 할 때 이상한 일이 일어납니다. 나는 함수 내에서 얻었다 값은 주요 기능에 살아남을 수 없습니다C에서 함수에서 여러 값을 반환

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

void build(char *ch){ 
    ch = malloc(30*sizeof(char)); 
    strcpy(ch, "I am a good guy"); 
} 

void main(){ 
    char *cm; 
    build(cm); 
    printf("%s\n", cm); 
} 

위의 프로그램은 그냥 쓰레기를 출력합니다. 그래서 나는 여기서 무엇이 잘못되었는지 알고 싶다. 결국, 나는 원래 명령 argv에서 나에게 두 개의 명령을 구문 분석 할 수있는이 parse(char **argv, char **cmd1, char **cmd2)과 같은 것을 원한다. 아무도 조금 설명 할 수 있다면 좋을 것 같습니다. 고마워.

+0

'문자 채널 ** ...'...'* 채널 = malloc에 ​​...'...'strcpy를 (* 채널 ...'...' 빌드 (& cm)'... –

+0

당신은 [포인터 포인터 필요] (http://stackoverflow.com/questions/18306935/need-of-pointer-to-pointer/18307020#18307020) –

+0

이런 식으로 생각하십시오. 함수가 인수'n'을 취하고이 함수가'n '('n = ...')에 새로운 값을 할당하고자한다면, 간접적 인 수준이 필요합니다. 즉'n'에 대한 포인터가 필요합니다 (typeof_n *). C의 모든 함수 인수는 값으로 전달됩니다. 즉, 복사본이 만들어 지므로, n''char *', 그 중 하나, 즉'char **'에 대한 포인터가 필요합니다. 그런 다음'* n = malloc (size);'라고 쓸 수 있습니다. 또한,'sizeof char'는'1'로 정의되어 있으므로'malloc' 호출에서 그 값을 사용할 필요가 없습니다. –

답변

5

build() 포인터를 ch 값으로 가져옵니다. 즉 포인터의 복사본이 함수에 전달됩니다. 그래서 그 값을 수정하면 함수가 종료 될 때 잃어 버리게됩니다. 포인터의 수정을 호출자의 컨텍스트에서 볼 수있게하려면 포인터에 대한 포인터를 전달해야합니다.

void build(char **ch){ 
    *ch = malloc(30*sizeof(char)); 
    strcpy(*ch, "I am a good guy"); 
} 

또한 여러 값을 반환해야하기 때문에 함수에 포인터를 전달할 필요가 없습니다. 또 다른 옵션은 멤버로 반환하려는 값이 포함 된 struct을 만들고 나서 struct의 인스턴스를 반환하는 것입니다. 값이 관련되어 있고 그것들을 함께 패키지하는 것이 합리적이라면 첫 번째 방법보다이 방법을 권장합니다. 이 값에 의해 전달되기 때문에 C에서, 당신은 포인터의 메모리 주소를 할당 할 수 없기 때문에

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

void build(char **ch){ 
    *ch = malloc(30 * sizeof(char)); 
    strcpy(*ch, "I am a good guy"); 
} 

int main() {  // main must return int 
    char *cm; 
    build(&cm); // pass pointer to pointer 
    printf("%s\n", cm); 
    free(cm);  // free allocated memory 
    return 0;  // main's return value, not required C99 onward 
} 
+0

사용법을 지적하는 데 도움이 될 수 있습니다 :'build (&cm);' –

+1

'// 메인은 반드시 void를 리턴해야합니다'나는 메인이 int를 리턴해야 함을 의미한다고 믿습니다 –

+0

@EdS. 감사합니다 .... – Praetorian

0

이것은 :


여기에 고정 버그 후 코드의 재상장입니다.

정말로 이것을하고 싶다면 포인터의 주소를 빌드 함수에 전달해야합니다.

참조 : Passing pointer argument by reference under C?

+1

"* 재 할당 할 수 없습니다 값으로 전달되기 때문에 포인터가 가리키는 메모리 주소 값 * "- 가능합니다. 포인터 자체에 새로운 값을 할당하고 호출자가 포인터를 볼 수 있다고 기대할 수는 없습니다. 포인터가 * 참조하는 값에 새로운 값을 할당 할 수 있습니다. 이미 간접적으로 필요한 수준을 가지고 있기 때문입니다. –

+0

이 단어를 잘못 말한 것 같습니다. 포인터가 값으로 전달되기 때문에 다른 메모리 주소를 가리킬 수 없다는 의미였습니다. 당연히 값을 바꿀 수 있습니다. 즉 포인터를 사용하는 전체 지점입니다 (말장난 의도) – George

+0

맞을 것입니다. 그 비트를 편집하면 내 downvote가 삭제됩니다. –

1

당신이 함수 내에서 malloc을 할 경우, 함수는 지역 변수이며, 외부에 영향을 미치지 않습니다 변화 안에, 당신은 ch 이후 외부 포인터에 주소를 전달해야 cm

void build(char **ch){ 
    *ch = malloc(30*sizeof(char)); 
    strcpy(*ch, "I am a good guy"); 
} 

void main(){ 
    char *cm; 
    build(&cm); 
    printf("%s\n", cm); 
} 

변수

그러나 더 나은 대신 당신이 영역 포인터가 가리키는에 원하는 것을 쓰기, 함수 내에서하지 malloc을한다. 이것은 C로 데이터를 얻기 위해 버퍼를 제공해야하는 일반적인 방법입니다. 이런 식으로 사용자는 자신 만의 메모리를 할당하거나 로컬 버퍼를 사용하기 때문에 메모리를 확보 할 필요가 없습니다. 당신의 예에서 잊어 맞는지

void build(char *ch){ 
    strcpy(ch, "I am a good guy"); 
} 

void main(){ 
    char *cm1; 
    cm1 = malloc(30*sizeof(char)); 
    build(cm1); 
    printf("%s\n", cm1); 

    char cm2[30]; 
    build(cm2); 

    printf("%s\n", cm2); 
    free(cm1);   // don't forget this 
} 
+0

와우, 고마워. 이것은 정말로 깨끗한 방법입니다. 그러나 여기서 왜 우리가 cm1과 cm2를 값으로 전달할 수 있습니까? 감사. –

+0

내가 말했듯이, 우리는 포인터가 아닌 데이터를 다루기를 원하기 때문에 포인터를 수정하는 대신 버퍼/데이터에 주소를 전달합니다. 호출자는 malloc을 호출하는 대신 로컬 배열을 선언하는 경우가 많습니다. 범위가 끝나면 자동으로 수명이 끝나고 처리 속도가 빨라지므로 자신의 사례와 같은 메모리를 확보 할 기회를 잊을 기회가 줄어 듭니다. memcpy 나 strcpy 또한 이것의 한 예입니다. 포인터의 주소가 아닌 데이터에 대한 포인터를 받아들입니다. –

관련 문제