当前位置: 首页 > 工具软件 > WePush > 使用案例 >

c语言push栈的用法,C语言中压栈函数push()的参数剖析

景鹏飞
2023-12-01

使用下面的代码进行压栈操作时错误的:

void WrongPush(struct node* head, int data) {

struct node* newNode = malloc(sizeof(struct node));

newNode->data = data;

newNode->next = head;

head = newNode; // NO this line does not work!

}

void WrongPushTest() {

List head = BuildTwoThree();

WrongPush(head, 1); // try to push a 1 on front -- doesn't work

}

原因如下:

The problem is all in the very last line where the 3-Step Link Indictates that we change the head pointer to refer to the new node. What does the line head = newNode; do in WrongPush()?

It sets a head pointer, but not the right one. It sets the variable named head local to WrongPush(). It does not in any way change the

variable named head we really cared about which is back in the caller WrontPushTest().

We need Push() to be able to change some of the caller's memory— namely the head

variable. The traditional method to allow a function to change its caller's memory is to

pass a pointer to the caller's memory instead of a copy. So in C, to change an int in the

caller, pass a int* instead. To change a struct fraction, pass a struct

fraction* intead. To change an X, pass an X*. So in this case, the value we want to

change is  struct node*, so we pass a  struct node** instead. The two stars

(**) are a little scary, but really it's just a straight application of the rule. It just happens

that the value we want to change already has one star (*), so the parameter to change it

has two (**). Or put another way: the type of the head pointer is "pointer to a struct

node." In order to change that pointer, we need to pass a pointer to it, which will be a

"pointer to a pointer to a struct node".

Instead of defining WrongPush(struct node* head, int data); we define

Push(struct node** headRef, int data);. The first form passes a copy of

the head pointer. The second, correct form passes a pointer to the head pointer. The rule

is: to modify caller memory, pass a pointer to that memory. The parameter has the word

"ref" in it as a reminder that this is a "reference" (struct node**) pointer to the

head pointer instead of an ordinary (struct node*) copy of the head pointer.

正确的代码

Here are Push() and PushTest() written correctly. The list is passed via a pointer to the

head pointer. In the code, this amounts to use of '&' on the parameter in the caller and use

of '*' on the parameter in the callee. Inside Push(), the pointer to the head pointer is

named "headRef" instead of just "head" as a reminder that it is not just a simple head

pointer..

/*

Takes a list and a data value.

Creates a new link with the given data and pushes

it onto the front of the list.

The list is not passed in by its head pointer.

Instead the list is passed in as a "reference" pointer

to the head pointer -- this allows us

to modify the caller's memory.

*/

void Push(struct node** headRef, int data) {

struct node* newNode = malloc(sizeof(struct node));

newNode->data = data;

newNode->next = *headRef; // The '*' to dereferences back to the real head

*headRef = newNode; // ditto

}

void PushTest() {

struct node* head = BuildTwoThree();// suppose this returns the list {2, 3}

Push(&head, 1); // note the &

Push(&head, 13);

// head is now the list {13, 1, 2, 3}

}

与C语言稍微不同,C++的用法如下:

/*

Push() in C++ -- we just add a '&' to the right hand

side of the head parameter type, and the compiler makes

that parameter work by reference. So this code changes

the caller's memory, but no extra uses of '*' are necessary -- we just access "head" directly, and the compiler makes that

change reference back to the caller.

*/

void Push(struct node*& head, int data) {

struct node* newNode = malloc(sizeof(struct node));

newNode->data = data;

newNode->next = head; // No extra use of * necessary on head -- the compiler

head = newNode; // just takes care of it behind the scenes.

}

void PushTest() {

struct node* head = BuildTwoThree();// suppose this returns the list {2, 3}

Push(head, 1); // No extra use & necessary -- the compiler takes

Push(head, 13); // care of it here too. Head is being changed by

// these calls.

// head is now the list {13, 1, 2, 3}

}The memory drawing for the C++ case looks the same as for the C case. The difference is

that the C case, the *'s need to be taken care of in the code. In the C++ case, it's handled

invisibly in the code.

Hope that can help!

END

 类似资料: