programing

C의 함수에 전달된 포인터를 수정하려면 어떻게 해야 하나요?

prostudy 2022. 6. 18. 09:17
반응형

C의 함수에 전달된 포인터를 수정하려면 어떻게 해야 하나요?

구조체 목록에 구조체를 추가하는 다음과 같은 코드가 있습니다.

void barPush(BarList * list,Bar * bar)
{
    // if there is no move to add, then we are done
    if (bar == NULL) return;//EMPTY_LIST;

    // allocate space for the new node
    BarList * newNode = malloc(sizeof(BarList));

    // assign the right values
    newNode->val = bar;
    newNode->nextBar = list;

    // and set list to be equal to the new head of the list
    list = newNode; // This line works, but list only changes inside of this function
}

이러한 구조는 다음과 같이 정의됩니다.

typedef struct Bar
{
    // this isn't too important
} Bar;

#define EMPTY_LIST NULL

typedef struct BarList
{
    Bar * val;
    struct  BarList * nextBar;
} BarList;

그리고 다른 파일에서 다음과 같은 작업을 수행합니다.

BarList * l;

l = EMPTY_LIST;
barPush(l,&b1); // b1 and b2 are just Bar's
barPush(l,&b2);

그러나 이 후에도 여전히 empty_LIST를 가리키고 있으며, barPush 내부에 작성된 수정 버전이 아닙니다.수정하려면 포인터에 대한 포인터로 목록을 전달해야 합니까? 아니면 다른 다크 주문이 필요합니까?

이렇게 하려면 포인터를 포인터에 전달해야 합니다.

void barPush(BarList ** list,Bar * bar)
{
    if (list == NULL) return; // need to pass in the pointer to your pointer to your list.

    // if there is no move to add, then we are done
    if (bar == NULL) return;

    // allocate space for the new node
    BarList * newNode = malloc(sizeof(BarList));

    // assign the right values
    newNode->val = bar;
    newNode->nextBar = *list;

    // and set the contents of the pointer to the pointer to the head of the list 
    // (ie: the pointer the the head of the list) to the new node.
    *list = newNode; 
}

그런 다음 다음과 같이 사용합니다.

BarList * l;

l = EMPTY_LIST;
barPush(&l,&b1); // b1 and b2 are just Bar's
barPush(&l,&b2);

Jonathan Leffler는 코멘트에서 새로운 리스트의 선두를 반환할 것을 제안했습니다.

BarList *barPush(BarList *list,Bar *bar)
{
    // if there is no move to add, then we are done - return unmodified list.
    if (bar == NULL) return list;  

    // allocate space for the new node
    BarList * newNode = malloc(sizeof(BarList));

    // assign the right values
    newNode->val = bar;
    newNode->nextBar = list;

    // return the new head of the list.
    return newNode; 
}

용도:

BarList * l;

l = EMPTY_LIST;
l = barPush(l,&b1); // b1 and b2 are just Bar's
l = barPush(l,&b2);

일반적인 답변: 변경할 항목에 포인터를 전달합니다.

이 경우 변경할 포인터에 대한 포인터가 됩니다.

C에서는 Everything은 값으로 전달됩니다.

포인터를 이렇게 포인터에 건네줍니다.

int myFunction(int** param1, int** param2) {

// now I can change the ACTUAL pointer - kind of like passing a pointer by reference 

}

이것은 전형적인 문제입니다.할당된 노드를 반환하거나 포인터의 포인터를 사용합니다.C에서는 X에 대한 포인터를 X를 수정할 함수에 전달해야 합니다.이 경우 포인터를 수정해야 하므로 포인터에 포인터를 전달해야 합니다.

네, 포인터를 포인터에 넘겨야 합니다.C는 인수를 참조가 아닌 값으로 전달합니다.

다른 함수에서 포인터를 수정하려면 다중 간접이라는 개념이 필요합니다.이것에 대해서는 나중에 설명하겠습니다.@geofftnz의 스포일러 솔루션은 다중 간접을 사용합니다.제가 하려고 하는 것은 C에서 여러 개의 인터다이렉션을 설명하도록 최선을 다하는 것입니다.

다음 두 가지 프로그램을 고려해 보십시오. 코드를 살펴보겠습니다.

다음 프로그램은 여러 개의 인터렉션을 사용하지 않으므로 실패합니다.

오류가 있는 프로그램:

// filename: noIndirection.c
#include <stdio.h>
#include <stdlib.h>

void allocater(int *ptrTempAllctr)
{
    ptrTempAllctr = malloc(sizeof(int));
    if (ptrTempAllctr == NULL) {
        perror("in allocater() memory allocation error");
        exit(EXIT_FAILURE);
    }
}

int main() 
{
    int *ptrMain = NULL;
    allocater(ptrMain);
    if (ptrMain == NULL) {
        printf("ptrMain is points to NULL\n");
        return 1;
    }
    //free(ptrMain);  // we don't have to free because it will be invalid free.
    return 0;
}

의 계획을noIndirection.c )가 ptrMainint을 입니다.함수에 전달된 경우 함수의 인수는 임시 변수이므로 함수 범위(본문)에서 임시 포인터 변수가 생성되며 범위를 벗어나면 삭제됩니다.

변수 " " " "ptrTempAllctr는 발신자가 무엇을 가리키는지(((인수)를 ).main).ptrMain은 (를 가리키고 있다)NULL는 함수에 인수로서 전달되었을 때를 가리킵니다.

를 사용하는 malloc()에 다른 할 수도 있습니다.ptrTempAllctr 후, 「」, 「」의 를.main " " " " " " " " " " ( 함수 ( )에 전달되었습니다allocater() 같은 있다(즉, 같은 데이터를 가리키고 있습니다.NULL이 명령어는 함수 호출 전에 지정되었습니다.

착신했을 때( 「」 「」 「」allocater()되지 않은 누수가 함수는 범위를 벗어납니다.일시 포인터 변수가 스택에서 팝업되고 메모리가 할당되지 않은 상태로 남아 메모리 누수가 발생합니다.이 제한을 회피하려면 여러 개의 간접방향을 사용해야 합니다.

다중 간접:

Multiple indirection when we use of pointer/s to pointer/s in varying level(with multiple `*`) eg: `int **pp, int ***ppp`, etc.

Address-of(Address-of(주소))를 사용하여 합니다.&).

여러 개의 간접 포인터 유형 변수가 하는 것은 위의 프로그램을 수정하기 위한 포인터 변수 자체에 대한 포인터입니다. 하면 ''를 전달할 수 .ptrMain로로 합니다.allocater(), 이 콜의

allocater(&ptrMain);

때문에, 의 프로그램 「 」은, 「 」를 참조해 주세요.noIndirection.c안 프로그램 .이치노withIndirection.c을 하다

int 포인터에 대한 포인터가 필요합니다.int **ptrMain의 함수 로서 「」를 지정합니다.allocater()(noDirection.c)로 설정합니다.

이것은 다음 프로그램에서 사용되었습니다.

다음 프로그램에서는 이전 프로그램의 버그를 해결하기 위해 여러 의 인터렉션을 사용하고 있습니다.

// filename: withIndirection.c
#include <stdio.h>
#include <stdlib.h>

void trueAllocater(int **ptrTrueAllocater)
{
    *ptrTrueAllocater = (int *) malloc(sizeof(int));
    if (ptrTrueAllocater == NULL) {
        perror("in trueAllocater() memory allocation error");
        exit(EXIT_FAILURE);
    }
}

int main(void) 
{
    int *ptrMain = NULL;
    trueAllocater(&ptrMain);
    if (ptrMain == NULL) {
        printf("memory not allocated\n");
        return EXIT_FAILURE;
    }

    printf("memory allocated and assigned to ptrMain");
    printf(" from trueAllocater\n");

    free(ptrMain);
    return EXIT_SUCCESS;
}

를 보다withIndirection.c참고하도록 하겠습니다.

변수 .ptrMain )trueAllocater(&ptrMain); change) trueAllocator로 ptrMaintrueAllocater()또는 다른 함수를 사용하려면 이 함수는 전달된 변수에 대한 현재 이해에 인수 선언에 추가된 다른 *를 추가하는 올바른 수준의 간접 포인터를 받아들여야 합니다.

수단까지 우리는 수단과통해 우리는 방법을 필요가 있다.trueAllocater()로서 기능하다로 기능 논쟁int **부터에서int *에에withIndirection.c로 와는 반대로에 반대하noIndirection.c그래서 간접 참조 수준 statisfied 것이다.그 때문에,간접레벨이 통계화 됩니다.

변수의 가 「」인 경우.ptrMain임시변통ptrTrueAllocater 변수 ""의 .ptrMain발신자 주소)main는 어떤 변수가 아니라 합니다.ptrMain은 (실제)NULL(하고 있다을 가리키다).main를 참조해 주세요.

「 」를 참조 하면,ptrTrueAllocater를 변경하다ptrMain예요.왜냐하면ptrTrueAllocater를 가리킵니다.mainptrMain그 내용이 아니라 변수 자체입니다.

되지 않은 ptrTrueAllocater입니다(「」).main의 variable의 variable()은 (으)로 표시됩니다.ptrMain최종 데이터를 얻으려면 참조를 1개 더 해야 합니다.

한 번 를 해제해야 를 알 수 있습니다.ptrMain를 하고, 「」 「 」 「 」 「 」ptrMain 번 .ptrMain, 「」입니다.NULL.

@PaulWicks 변경하려고 했으므로 포인팅 위치를 할당하거나 변경하려면 참조를 한 번 취소해야 합니다.

포인터를 사용하는 다중 간접의 목적은 포인터가 필요한 다차원 배열을 만들고 포인터 인수를 전달하는 것입니다.

다음과 같이 조작해야 하는 유형에 따라 변수를 변경해야 합니다.

선언에 *를 추가할 때마다 포인터 간접 레벨이 증가하며 참조 해제될 때마다 데이터에 근접하는 포인터 간접 레벨이 감소합니다.

이 문제는 필요한 포인터 변수에 할당되어 있는 발신자 함수에 주소를 되돌리는 것으로 해결할 수 있습니다.

네, 이 다중 간접 변수 구문을 사용하여 1차원 또는 다차원 배열을 만들 수 있습니다.이것은 처음에 초보자들을 혼란스럽게 할 것이다.만약 그들이 많은 코드를 읽을 시간을 둔다면 그들은 그들 사이의 차이를 찾을 수 있을 것이다.

제가 틀렸다면 정정해주시고, 피드백과 여러 간접 포인터의 다른 사용법을 알려주세요.제가 영어를 잘못해서 죄송합니다.여러 가지 지시사항을 이해하는 데 도움이 되는 자료입니다.https://boredzo.org/pointers/ #function_http://rt_lt.rule.http://https://cseweb.ucsd.edu/

언급URL : https://stackoverflow.com/questions/766893/how-do-i-modify-a-pointer-that-has-been-passed-into-a-function-in-c

반응형