2014-12-17 3 views
2

이 코드를 작성하는 데 오랜 시간을 보냈을 때 누군가가 함수에 대한 인수로 문자열에 대한 포인터를 전달할 때 왜 2 별이 필요한지 설명 할 수 있습니까? ? 포인터는 정의에 따라 특정 변수가 배치 될 메모리에 주소를 유지합니다. 그래서 그것은 자신의 주소를 가지고 있고이 주소 아래에 다른 변수에 대한 주소 인 변수입니다. 괜찮아. 따라서 함수에 포인터를 전달하면 포인터 주소를 함수에 전달해야하므로 앰퍼샌드를 사용합니다. 벌금. 그런데 어떻게됩니까? 이 함수는 메모리에서이 포인터에있는 정보를 수신합니다. 괜찮아. 이것은 내가 이해하는 것입니다. 내가 이해할 수없는 것은 내가 왜 함수와 그것의 주장을 정의 할 때 두 개의 별이 필요한지입니다. char 변수에 대한 포인터를 전달하고 있습니다. 왜 void wpisuj (char * w)를 사용하지 않을까요? 왜 wpisuj (char ** w)입니까? 메모리 할당이 이해할 수있다 - 나는 malloc을 가진 메모리를 예약했고 malloc은이 메모리의 주소를 반환한다. 그래서 나는이 주소를 변수 w의 값으로 둔다. 그리고 * w가 포인터이고 메모리에 새로 생성 된 장소의 주소를 유지한다면 * w를 사용하여 왜 거기에 문자열을 넣을지 모르겠다. * (* w)가 아니어야합니까? * w는 예약 된 메모리의 주소이므로 * (* w)는이 메모리의 내용입니다.왜 포인터에 문자열을 함수에 전달할 때

요약. 왜 내가 이해가 안 돼요 : 1) wpisuj (char * w) 대신 wpisuj (char * w) 2) strcpy ( (* w), bufor) 대신 strcpy (w, bufor) 이유가

#include<stdlib.h> 
#include<stdio.h> 
#include<string.h> 
# define SIZE 256 

void wpisuj(char** pw){ 
    char bufor[256]; 
    scanf("%s", bufor); 
    int l; 
    l=strlen(bufor)+1; 
    *pw=(char*)malloc(l*sizeof(char)); 
    strcpy(*pw, bufor); 
} 


int main(){ 
    char* w; 
    wpisuj(&w); 
    printf("%s", w); 

    return 0; 
} 

그리고 메모리를 확보 해달라고 요청할 수도 있습니다.

int main(){ 
    w=malloc(sizeof(buffer)+sizeof(char)); 
/* some code before */ 
    free(w); 
} 
+3

두 개의 별은 포인터에 대한 포인터이기 때문에 .... – duffymo

+3

'*'= pointer. '**'= 포인터에 대한 포인터. 그게 전부 야 –

+0

함수에서 다른 변수 이름을 사용하면 도움이 될 것입니다.함수의'w'는 main의'w'에 대한 포인터입니다. 아마도 그것을'pw'라고 부르면됩니다. 함수에서'* pw'는 main에서'w'와 같은 변수를 의미합니다. –

답변

4

분명히 것를 들어 출력이됩니다 다음과 같은 간단한 프로그램

#include <stdio.h> 

void f(int x) 
{ 
    x = x + 20; 
} 

int main(void) 
{ 
    int x = 10; 

    printf("Before the call f(x) x = %d\n", x); 

    f(x); 

    printf("After the call f(x) x = %d\n", x); 

    return 0; 
} 

을 고려

당신이 x는 함수 f에 chenged되지 않은 참조로
Before the call f(x) x = 10 
After the call f(x) x = 10 

때문에 사본 함수 거래 object x는 main에 정의됩니다. 당신이 기능을 우리가 함수에 원본 객체의 x의 주소를 통과하기 때문에 출력이

Before the call f(x) x = 10 
After the call f(x) x = 30 

될 것입니다이 경우 다음과 같은 방법으로 다음

#include <stdio.h> 

void f(int *x) 
{ 
    *x = *x + 20; 
} 

int main(void) 
{ 
    int x = 10; 

    printf("Before the call f(x) x = %d\n", x); 

    f(&x); 

    printf("After the call f(x) x = %d\n", x); 

    return 0; 
} 

를 다시 작성합니다 경우

및 함수 내에서 원래 객체 자체가 변경되었습니다.

게시물의 포인터와 동일합니다.

당신이 포인터를 메인에

char *p; 

을 정의하고

void f(char *p); 

다음 함수가 원래 객체의 복사본을 처리 할 함수에 인수로 전달됩니다. 사본의 변경 사항은 원래 포인터에 영향을 미치지 않습니다. 함수가

void f(char **p); 

같이 선언해야하다이 포인터에 대한 포인터를 전달하고

f(&p); 
4

을 : 나는 것) (주 메모리를 해제하는 경우,

void free_memory(char **w){ 
    free(*w); 
} 

을하지만 : 나는 (아래의 코드와 같이)이 별의 corect 양이 생각에 수정나요 이유 wpisujchar**을 전달하면 메모리가 함수에 할당되고 *w에 할당되면 wpisuj에서 반환 할 때 변경 내용이 호출 함수에 표시됩니다.

당신이 가지고있는 경우 :

void wpisuj(char* w){ 
    char bufor[256]; 
    scanf("%s", bufor); 
    int l; 
    l=strlen(bufor)+1; 
    w=(char*)malloc(l*sizeof(char)); 
    strcpy(w, bufor); 
} 

w에 대한 변경 사항은 로컬 변화이다. 호출 함수는 변경 사항을 보지 못합니다.

0

글쎄, 나는 당신의 질문에 대한 이해를 설명 할께. 변수를 변경하기 위해 함수를 사용하려면 주소를 보내야한다. 그렇지 않으면 함수 내에서 로컬 복사본을 변경한다. 함수가 반환되면 반환됩니다.

1) 기본적으로 주요, 당신은 아무것도를 가리키는 포인터를 만들고 당신이 뭔가를 가리 있도록 기능 wpisuj()를 호출 당신에. 위의 아이디어를 사용하여 포인터의 메모리 위치를 보내야 함수가 포인터의 위치를 ​​변경할 수 있습니다. &w 대신 w만을 보낸 경우 주소 사본을 보내고 주소를 변경할 수 없으므로 주소 사본을 보내 게됩니다.

2) 함수 strcpy은 사용자 입력 주소가 아닌 string의 주소 인 특정 입력을 필요로합니다.따라서 w이 가리키는 위치를 얻으려면 을 사용합니다.

0

과 같이 호출해야 할 당신이해야 할 첫 번째 예에서와 같이 아래의 코드는 다른 표시 그래서 같은 일을하는 방법. 주요 차이점은 wpisuj 함수입니다. 은 새로 할당 된 문자열 (mainw에 할당 됨)에 대한 포인터 인을 반환합니다. 이 기술은 wpisujmain's 복사본 w을 수정할 필요가 없기 때문에 포인터에 포인터를 사용하지 않아도됩니다.

다른 차이점

  • 오류 검사 : scanfmalloc 표시 값은
  • 에는 메모리 누수 체크되어 있음 : 끝에 free(w)
  • 나은 보안 : scanf%255s는 버퍼 오버 플로우를 사용 방지

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

char *wpisuj(void) 
{ 
    char bufor[256]; 

    if (scanf("%255s", bufor) != 1) 
     return(NULL); 

    char *w = malloc(strlen(bufor) + 1); 

    if (w != NULL) 
     strcpy(w, bufor); 

    return(w); 
} 

int main() 
{ 
    char *w; 

    if ((w = wpisuj()) != NULL) 
    { 
     printf("%s\n", w); 
     free(w); 
    } 

    return 0; 
} 
0

왜 이중 포인터가 필요합니까?

귀하의 질문에 대한 답변입니다. 대답은 다음과 같습니다. 실제 매개 변수 (호출자가 전달한 값의 사본)와 마찬가지로 함수에 전달 된 포인터는 실제로 선언 된 범위의 값을 보유합니다 (이 경우에는 호출자 함수에서 아무 것도 변경하지 않고 호출됩니다. w의 값을 변경하려고하기 때문에 원하는 결과가 아닙니다.

당신은 같은 것을 할 경우 : 당신은 그냥 MyFunction() 내부 p가 가리키는 주소를 변경하기 때문에

void MyFunction(int* p) { 
    //`p`'s value, like `a`'s value, is NULL 
    *p=(char *)malloc(256*sizeof(char)); 
    //`p`'s value is the starting address of the buffer, but `a` didn't change 
    return; 
} 

int main() { 
    char* a; 
    a=NULL; 
    MyFunction(a); 
    return 0; 
    //`a`'s value is still NULL, because MyFunction() changed only its own copy of `a` 
} 

아무것도가 발생하지합니다.

그래서, 당신은 정수를 위해 할 것 같이

void MyFunction(int* p) { 
    *p=1; 
    return; 
} 

int main() { 
    int a; 
    a=0; 
    MyFunction(&a); 
    printf("%d", a); 
    return 0; 
} 

포인터에 대해 동일한 작업을 수행합니다 나는를 정의 할 때 나는 두 개의 별이 필요한 이유

void MyFunction(int** p) { 
    *p=(char *)malloc(256*sizeof(char)); 
    return; 
} 

int main() { 
    char* a; 
    a=NULL; 
    MyFunction(&a); 
    return 0; 
} 

는 내가 이해하지 못하는 것은 함수와 그 인수. char 변수에 대한 포인터를 전달하고 있습니다.

wpisuj (char * w)를 void 화하지 않는 이유는 무엇입니까? 왜 wpisuj (char ** w)입니까? 코드에서

봐 :

wpisuj(&w);

여기 amperstand 역 참조 포인터 w. 즉, 표현 &w의 전체 값은 주소w입니다. 그래서 당신이 전달하는 char 변수에 포인터에 대한 포인터에 대한 포인터의 주소는입니다. 맞습니다 : 정수를 변경해야하는 경우 정수의 주소를 전달합니다. 포인터를 변경해야하는 경우 포인터의 주소를 전달합니다. 따라서 wpisuj(char** w)을 사용하는 것이 맞습니다.

그리고 * w가 포인터이고 메모리에 새로 생성 된 장소의 주소를 유지한다면 * w를 사용하여 왜 거기에 문자열을 넣을지 이해할 수 없습니다.

당신은 문자열을 배치하지 않는 때문에 : w 같은 전에 말했듯이 (wpisuj() 내부하는) 포인터에 대한 포인터가 문자에있는 경우, *w (wpisuk() 내부)의 동등는 char에 대한 포인터이며, *(&w)main()으로 설정하면 w의 값이 main()입니다. 그래서 당신이하고있는 일은 malloc()에 의해 반환 된 값을 포인터 wmain()에 할당하는 것입니다.

관련 문제