简体   繁体   English

C 堆栈实现。 关于解引用和双指针的问题

[英]C stack implementation. Question about dereference and double pointers

Good day everyone.今天是个好日子。 I am new to C and stack overflow too so go easy on me please:) I have few question about this stack code in C:我是 C 和堆栈溢出的新手,所以 go 对我来说很容易:) 我对 C 中的这个堆栈代码几乎没有疑问:

1) push(&stackPtr, value); 1) push(&stackPtr, value); why stackPtr has to have & sign?为什么 stackPtr 必须有 & 签名? and what function will get without it?没有它,function 会得到什么?

2) topPtr = newPtr; 2) topPtr = newPtr; why topPtr has to be *topPtr?为什么 topPtr 必须是 *topPtr? And what is going on with the code without it?没有它的代码会发生什么?

3) *topPtr = (*topPtr)->nextPtr; 3) *topPtr = (*topPtr)->nextPtr; why *topPtr has to have *?为什么 *topPtr 必须有 *? and what gonna be without * sign?没有*号会怎样?

Thank for any answers in advance.提前感谢您的任何答案。

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

// self-referential structure                     
struct stackNode {                                   
   int data; // define data as an int             
   struct stackNode *nextPtr; // stackNode pointer
};

typedef struct stackNode StackNode; // synonym for struct stackNode
typedef StackNode *StackNodePtr; // synonym for StackNode*

// prototypes
void push(StackNodePtr *topPtr, int info);
int pop(StackNodePtr *topPtr);
void printStack(StackNodePtr currentPtr);
void instructions(void);

// function main begins program execution
int main(void)
{ 
   StackNodePtr stackPtr = NULL; // points to stack top
   int value; // int input by user

   instructions(); // display the menu
   printf("%s", "? ");
   unsigned int choice; // user's menu choice
   scanf("%u", &choice);

   // while user does not enter 3
   while (choice != 3) {

      switch (choice) { 
         // push value onto stack
         case 1:      
            printf("%s", "Enter an integer: ");
            scanf("%d", &value);
            push(&stackPtr, value);
            printStack(stackPtr);
            break;
         // pop value off stack
         case 2:      
            // if stack is not empty
            if (stackPtr != NULL) {
               printf("The popped value is %d.\n", pop(&stackPtr));
            }

            printStack(stackPtr);
            break;
         default:
            puts("Invalid choice.\n");
            instructions();
            break;
      } // end switch

      printf("%s", "? ");
      scanf("%u", &choice);
   }

   puts("End of run.");
}

// display program instructions to user
void instructions(void)
{ 
   puts("Enter choice:\n"
      "1 to push a value on the stack\n"
      "2 to pop a value off the stack\n"
      "3 to end program");
}

// insert a node at the stack top
void push(StackNodePtr *topPtr, int info)
{ 
   StackNodePtr newPtr = malloc(sizeof(StackNode));

   // insert the node at stack top
   if (newPtr != NULL) {           
      newPtr->data = info;
      newPtr->nextPtr = *topPtr;
      topPtr = newPtr; 
   }                     
   else { // no space available
      printf("%d not inserted. No memory available.\n", info);
   } 
}

// remove a node from the stack top
int pop(StackNodePtr *topPtr)
{ 
   StackNodePtr tempPtr = *topPtr;             
   int popValue = (*topPtr)->data;  
   *topPtr = (*topPtr)->nextPtr;
   free(tempPtr);               
   return popValue;
}

// print the stack
void printStack(StackNodePtr currentPtr)
{ 
   // if stack is empty
   if (currentPtr == NULL) {
      puts("The stack is empty.\n");
   } 
   else { 
      puts("The stack is:");

      // while not the end of the stack
      while (currentPtr != NULL) { 
         printf("%d --> ", currentPtr->data);
         currentPtr = currentPtr->nextPtr;
      }

      puts("NULL\n");
   } 
}

This is all pretty basic C, so I'll try to be as clear as possible, but I suggest you to carefully read reference books on the topic.这都是非常基本的 C,所以我会尽量说清楚,但我建议你仔细阅读有关该主题的参考书。

This code defines a structure stackNode which contains some data, and a "pointer" to this same structure.此代码定义了一个包含一些数据的结构stackNode和一个指向同一结构的“指针”。

Because stackNode is a structure, when you pass it as a parameter to a function, the compiler creates a copy of it and gives it to the function.因为stackNode是一个结构,所以当您将它作为参数传递给 function 时,编译器会创建它的副本并将其提供给 function。 This is called "passing parameter by copy".这称为“通过副本传递参数”。 Example:例子:

StackNode node;
foo(node) ;

void foo(StackNode  n) {
   /* foo() function can use the parameter n which is a local copy of node.
      you can modify n in the foo() function, that will not modify the node variable */
}

This implies that the function can not modify your original data.这意味着 function 无法修改您的原始数据。 It can modify the function's local copy, which is lost at the end of the function.它可以修改函数的本地副本,该副本在 function 的末尾丢失。

If you want to modify the given parameter, you must pass the parameter "by address" rather than "by copy".如果要修改给定的参数,则必须“通过地址”而不是“通过复制”传递参数。 You do it this way:你这样做:

StackNode node;
foo(&node) ;

void foo(StackNode  *n) {
   /* foo() function accesses the node variable via its address n. (*n) represents
      the content at address n, which is node. */
}

In this code, the function foo() gets the address of a StackNode (and not a copy of a StackNode).在此代码中,function foo() 获取 StackNode 的地址(而不是 StackNode 的副本)。 By "de-referencing" the address, you can access the content that is "pointed to" by the pointer, and therefore modify it "for real".通过“取消引用”地址,您可以访问指针“指向”的内容,从而“真正地”修改它。 "De-referencing" is performed by the "*" operator, while the "&" operator gives the "reference" (the address) of a variable. “取消引用”由“*”运算符执行,而“&”运算符给出变量的“引用”(地址)。

So now, to your code.所以现在,到你的代码。 I'll answer your questions in a slightly different order, to make it clearer (I think).我将以稍微不同的顺序回答您的问题,以使其更清楚(我认为)。

What void push(StackNodePtr *topPtr, int info) does is to malloc a new node, make it point to the current topPtr, and then modifies topPtr to point to this new node. void push(StackNodePtr *topPtr, int info)所做的就是给malloc一个新的节点,让它指向当前的topPtr,然后修改topPtr指向这个新的节点。

Therefore it modifies topPtr.因此它修改了topPtr。

Therefore topPtr needs to be passed by reference.因此 topPtr 需要通过引用传递。

Therefore you need void push(StackNodePtr *topPtr, int info) and not void push(StackNodePtr topPtr, int info)因此你需要void push(StackNodePtr *topPtr, int info)而不是void push(StackNodePtr topPtr, int info)

Therefore you need to call it with push(&stackPtr,value)因此,您需要使用push(&stackPtr,value)调用它

If you call push(stackPtr,value) , then:如果您调用push(stackPtr,value) ,则:

  • First of all, your compiler should complain (at least raise a warning)首先,您的编译器应该抱怨(至少发出警告)
  • You will crash one day or another as you will be modifying unknown zones of memory您将有一天或另一天崩溃,因为您将修改 memory 的未知区域

You should also now understand why you need (*topPtr) = newPtr instead of topPtr = newPtr .您现在还应该了解为什么需要(*topPtr) = newPtr而不是topPtr = newPtr Because you want to modify stackPtr, and you need to de-reference topPtr.因为要修改stackPtr,需要取消引用topPtr。

Same in the latter code.在后面的代码中相同。

This said, I can think of much easier to implement a stack... ;-)这就是说,我可以想到更容易实现堆栈... ;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM