2009-11-23 3 views
1

스택을 구현하는 연결된 목록의 교과서 예제를보고 있습니다. 왜 스택에 대한 포인터를 포인터를 사용하여 밀어 넣기 작업에 필요한 이해가되지 않습니다. 다음 예를 참조하십시오 : 사람이 푸시 방법의 첫 번째 매개 변수는 포인터에 대한 포인터 인 이유를 명확히 도움이 될 수있는 경우푸시 기능을 만들 때 스택 포인터를 사용하는 이유는 무엇입니까?

bool push(Element **stack, void *data) 
{ 
    Element *elem = new Element; 
    if(!elem) return false; 

    elem->data = data; 
    elem->next = *stack; 
    *stack = elem; 
    return true; 
} 

, 나는 그것을 대단히 감사하겠습니다. 감사.

놀랍고도 훌륭한 도움을 주셔서 감사합니다.

+0

C는 아무튼 새로운 k가있다. eyword. C++ 않습니다. 즉, C++은 메모리 할당 실패에 대한 예외를 던지므로 null을 확인할 필요가 없습니다. – GManNickG

+0

또한 포인터 대신 참조를 사용하여 컴파일러에서 더러운 작업을 수행 할 수 있습니다. – GManNickG

답변

8

이 함수는 요소 포인터의 값을 수정해야하므로 포인터는 포인터가 필요합니다.

다른 말로 표현하면, 함수는 그 것을 수정해야 할 때 무언가의 포인터를 취합니다.

이 경우 그 무엇인가는 포인터 자체입니다. 그래서 함수는 포인터에 대한 포인터를 가져온다.

+0

OK ... 내가 틀렸다면 나에게 맞춰라. 링크 된리스트의 끝 부분에 무언가를 추가하기를 원한다면 (푸시 함수가 아니라 단지 addItem 함수), 포인터에 대한 포인터가 필요 없다. 명부? – Lou

+0

일반적으로 마지막 요소를 가리키는 포인터가있을 것이고, NULL 값을 가진 포인터가 포함될 것입니다. 예, 마지막 요소에 대한 포인터 만 있으면됩니다. –

+0

글쎄.이 경우의'** stack' 포인터는리스트의 끝 위치를 추적하기위한 것입니다. 그러한 값을 추적 할 필요가 없다면, 아니요, 링크 된 목록에 요소를 추가 할 때 전혀 신경 쓰지 않아도됩니다. 당신은 아마도 목록 자체에 포인터를 사용할 수 있습니다. – int3

0

포인터를 업데이트해야합니다.

목록은 Element에 대한 포인터 일뿐입니다. 그래서 당신은 당신이 경우에 당신은 이중 포인터를 사용하지 않을 것을 볼

bool push(List* stack, void* data); 

하지 않음이를 다시 작성할 수 , 실제 선언했다에서 원래 목록을 변경하지 않을

bool push(List stack, void* data); 

모든. 당신 업데이트 수 있기 때문에

그러나 교대

bool push(Element* &stack, ...) 

도 OK입니다.

4

포인터는 단순히 을 보유하는 변수이며 그 값은 메모리 주소입니다.

포인터에 대한 포인터는 단순히 값을 보유하는 변수이기도합니다. 이 값은 포인터의 메모리 주소입니다.

포인터를 변경하려는 경우 포인터에 대한 포인터를 사용합니다.

//Not a very useful example, but shows what I mean... 
void getOffsetBy3Pointer(const char *pInput, char **pOutput) 
{ 
    *pOutput = pInput + 3; 
} 

는 그리고 당신은이 기능과 같이 전화 :

const char *p = "hi you"; 
char *pYou; 
getOffsetBy3Pointer(p, &pYou); 
assert(!stricmp(pYou, "you")); 

이제 우리는 하나의 포인터로이 기능을 구현하기 위해 노력하면 무슨 일이 일어날 지 고려한다.

//Note: This is completely wrong 
void BadGetOffsetBy3Pointer(const char *pInput, char *pOutput) 
{ 
    //*pOutput refers to the first actual char element that pOutput points to. 
    pOutput = pInput + 3; 
    //pOutput now points to pInput + 3, but the variable we passed in remains distinct. 
} 

그리고이 기능과 같이 호출 다음 BadGetOffsetBy3Pointer에

const char *p = "hi you"; 
char *pYou = NULL; 
BadGetOffsetBy3Pointer(p, pYou); 
assert(pYou == NULL); 

주, 우리는 문자의 일부를 변경 할 수 있지만 우리는에 포인트를 pYou 무엇을 변경할 수 있습니다.

0

스택은 그 위에 밀어 넣은 마지막 요소에 대한 포인터로 나타냅니다. 요소를 푸시하여 스택을 변경하려면이 포인터를 업데이트해야합니다. 따라서 포인터를 푸시 함수에 전달해야합니다. 사람이 푸시 기능을 사용하는 방법에

0

봐는 :

Data d1, d2; 

Stack *s = null; // s := null 
push(&s, &d1); // s := {d1}->null 
push(&s, &d2); // s:= {d2}->{d1}->null 

이제 성장 스택의 상단을 가리 키도록 푸시에 의해 수정 된 변수들, 계속 사용할 수 있습니다.

스택에서 항상 포인터를 최상위로 유지하려는 것이고 push 함수를 사용하면이 포인터를 더 쉽게 유지 관리 할 수 ​​있습니다.

1

스택은 기본적으로 연결된 포인터 목록입니다. 각 하나는 그 아래를 가리키고 있습니다. 새 요소가있어서 그 요소가 목록에서 처음으로 오도록하려는 경우 (따라서 "스택"이라는 용어는 목록의 시작 부분을 변경해야합니다.)

" "리스트의 헤드 포인터, 당신은 그 포인터의 주소를 필요로하기 때문에이 라인의

1

:..

*stack = elem; 

은 기본적으로 당신이 함수 내에서 원래의 포인터를 수정하는

관련 문제