What are the memory requirements for the Pop and Push algorithms in C?

  • Context: MHB 
  • Thread starter Thread starter evinda
  • Start date Start date
  • Tags Tags
    Memory Push
Click For Summary

Discussion Overview

The discussion revolves around the memory requirements and implementation details of the Pop and Push algorithms for a stack in C. Participants explore the implications of passing pointers by value versus by reference, as well as the memory needed for local variables and function parameters.

Discussion Character

  • Technical explanation
  • Conceptual clarification
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • Some participants explain that in C, the Push function does not modify the original pointer because the parameter S is passed by value, not by reference.
  • Others suggest that to modify the original pointer, the function should take a pointer to a pointer (e.g., pointer *pS) instead.
  • There is a discussion about how the memory requirements for the Pop function can vary based on course definitions, including the memory for parameters, local variables, and stack frames.
  • Some participants provide examples of pointer usage in C, explaining the concept of pointers to pointers and how typedefs can clarify pointer types.
  • Participants express confusion about the concept of stack frames and the memory needed for function calls, prompting further explanations.
  • There is a proposal to count the memory needed for inputs and pointers when determining the total memory requirements for the function.

Areas of Agreement / Disagreement

Participants generally agree on the mechanics of passing pointers in C, but there is no consensus on the exact memory requirements for the Pop function, as it may depend on course-specific definitions and assumptions.

Contextual Notes

Limitations include the lack of consensus on how to account for memory requirements, as well as varying interpretations of what constitutes a stack frame and how to calculate memory for function parameters.

Who May Find This Useful

This discussion may be useful for students and practitioners interested in understanding stack operations in C, memory management, and pointer manipulation.

evinda
Gold Member
MHB
Messages
3,741
Reaction score
0
Hello! (Smile)

I am looking at the algorithms [m]Pop[/m] and [m]Push[/m] of a stack:

Code:
void Push(info x, pointer S)
       pointer P; /* temporary pointer */
       P=NewCell(NODE); /* malloc() */
       P->data=x;
       P->next = S;
       S=P; /* This wouldn't give the right result in C*/

Why doesn't [m]S=P[/m] work in C?

Code:
info Pop(pointer S)
      info x;
      if (IsEmptyStack(S)) then error;
      else
           x=Top(S);
           S=S->next;
      return x;

How can we find how much memory the algorithm [m]Pop[/m] needs? (Thinking)
 
Technology news on Phys.org
Hey! (Smile)

evinda said:
Code:
void Push(info x, pointer S)
       ...
       S=P; /* This wouldn't give the right result in C*/

Why doesn't [m]S=P[/m] work in C?

That is because S is passed by value instead of by reference.
Changing S won't change the original pointer that was passed to the function. (Nerd)

To make it work in C, we would need:
Code:
void Push(info x, pointer *pS)
       ...
       *pS=P; /* This will give the right result in C*/
This means the pS is a pointer to a pointer, giving us the opportunity to change the original pointer. (Wasntme)

Alternatively, we can do in C++:
Code:
void Push(info x, pointer& S)
       ...
       S=P; /* This will give the right result in C++ "if" we use a reference */
The symbol & means that S is passed by reference.

Code:
info Pop(pointer S)
      info x;
      if (IsEmptyStack(S)) then error;
      else
           x=Top(S);
           S=S->next;
      return x;

How can we find how much memory the algorithm [m]Pop[/m] needs? (Thinking)

Counting the memory may depend on the course you are following.
If we try to account for everything (and many courses don't), we have:
  • The required memory to pass the parameter S (1 unit).
  • The required memory for the local variable x (sizeof info).
  • The required memory for a stack frame and the return address (in practice 2 units, but this may depend on your course that may choose to neglect this).
  • The maximum of the required memory for IsEmptyStack(S) and Top(S).
(Wasntme)
 
I like Serena said:
Hey! (Smile)
That is because S is passed by value instead of by reference.
Changing S won't change the original pointer that was passed to the function. (Nerd)

To make it work in C, we would need:
Code:
void Push(info x, pointer *pS)
       ...
       *pS=P; /* This will give the right result in C*/

A ok.. (Nod)

I like Serena said:
This means the pS is a pointer to a pointer, giving us the opportunity to change the original pointer. (Wasntme)

Could you explain me why pS is a pointer to a pointer? :confused:

I like Serena said:
Alternatively, we can do in C++:
Code:
void Push(info x, pointer& S)
       ...
       S=P; /* This will give the right result in C++ "if" we use a reference */
The symbol & means that S is passed by reference.

Aha.. interesting! (Nerd)

I like Serena said:
Counting the memory may depend on the course you are following.
If we try to account for everything (and many courses don't), we have:
  • The required memory to pass the parameter S (1 unit).
  • The required memory for the local variable x (sizeof info).
  • The required memory for a stack frame and the return address (in practice 2 units, but this may depend on your course that may choose to neglect this).
  • The maximum of the required memory for IsEmptyStack(S) and Top(S).
(Wasntme)

Could you explain me what a stack frame is? (Thinking)

According to my notes, the memory is: inputs & (n+1) pointers (if the stack has n elements).. (Talking)
 
evinda said:
Could you explain me why pS is a pointer to a pointer? :confused:

Suppose we have the following code.
Code:
struct Node {
  int value;
};

Node node;
Node *pNode = &node;
Node *ppNode = &pNode;

Then [m]node[/m] is a global object, [m]pNode[/m] is a pointer to that node, and [m]ppNode[/m] is a pointer to a pointer to that node.
Could you explain me what a stack frame is? (Thinking)

The stack is some space in the memory of the computer where all parameters to functions, and all local variables go.
It's called a stack, because we "push" a function call on top of the stack together with all its parameters and local variables.
And when the function call is done, they all get "popped" again from the top.

When the function call is made, the computer needs to keep track where those parameters and local variables actually are, and also to which address he should return when the function call is done. To do that, a marker is also pushed onto the stack, together with the return address.
These make up the so called stack frame. (Nerd)
According to my notes, the memory is: inputs & (n+1) pointers (if the stack has n elements).. (Talking)

That sound like the total memory or something of a RAM machine.
A RAM machine keeps track of $n$ registers, and additionally it will get inputs that it will read.
If those are limited, we need to figure out how many of those a function will need, before we know if that function can be executed by the RAM machine. (Wasntme)
 
I like Serena said:
Suppose we have the following code.
Code:
struct Node {
  int value;
};

Node node;
Node *pNode = &node;
Node *ppNode = &pNode;

Then [m]node[/m] is a global object, [m]pNode[/m] is a pointer to that node, and [m]ppNode[/m] is a pointer to a pointer to that node.

Code:
void Push(info x, pointer S)
       pointer P; /* temporary pointer */
       P=NewCell(NODE); /* malloc() */
       P->data=x;
       P->next = S;
       S=P;
I thought that when the function is like that in C, S is not a pointer, but only if the parameter would be *S.
So, why is *S a pointer to a pointer? (Worried)
I like Serena said:
The stack is some space in the memory of the computer where all parameters to functions, and all local variables go.
It's called a stack, because we "push" a function call on top of the stack together with all its parameters and local variables.
And when the function call is done, they all get "popped" again from the top.

When the function call is made, the computer needs to keep track where those parameters and local variables actually are, and also to which address he should return when the function call is done. To do that, a marker is also pushed onto the stack, together with the return address.
These make up the so called stack frame. (Nerd)

I haven't understood it... (Sweating) Could you explain it further to me? :confused:
I like Serena said:
That sound like the total memory or something of a RAM machine.
A RAM machine keeps track of $n$ registers, and additionally it will get inputs that it will read.
If those are limited, we need to figure out how many of those a function will need, before we know if that function can be executed by the RAM machine. (Wasntme)

So, what do we have to count, in order to find the needed memory? (Worried)
 
evinda said:
I thought that when the function is like that in C, S is not a pointer, but only if the parameter would be *S.
So, why is *S a pointer to a pointer? (Worried)

There has to be a typedef:
Code:
typedef Node *pointer;
It means that when we refer to [m]pointer S[/m] it is actually [m]Node *S[/m].
And [m]pointer *pS[/m] is actually [m]Node **pS[/m].
I haven't understood it... (Sweating) Could you explain it further to me? :confused:

What is it that you do not understand? :confused:

To be fair, this is a concept that may requires a bit more than only a couple of lines to explain. (Tauri)
So, what do we have to count, in order to find the needed memory? (Worried)

What do you think we have to count? (Wondering)
 
I like Serena said:
There has to be a typedef:
Code:
typedef Node *pointer;
It means that when we refer to [m]pointer S[/m] it is actually [m]Node *S[/m].
And [m]pointer *pS[/m] is actually [m]Node **pS[/m].

So, you mean that in C, it should be like that?

Code:
void Push(info x, pointer *S)
       pointer *P; /* temporary pointer */
       P=NewCell(NODE); /* malloc() */
       P->data=x;
       P->next = S;
       **S=P;

Or have I understood it wrong? :confused:
I like Serena said:
What do you think we have to count? (Wondering)
How can we figure out how many registers and inputs the function needs in our case? (Thinking)
 
evinda said:
So, you mean that in C, it should be like that?

Code:
void Push(info x, pointer *S)
       pointer *P; /* temporary pointer */
       P=NewCell(NODE); /* malloc() */
       P->data=x;
       P->next = S;
       **S=P;

Or have I understood it wrong? :confused:

Does it compile? (Wondering)

How can we figure out how many registers and inputs the function needs in our case? (Thinking)

How many registers do you count that would be needed, counting the things we can? (Wondering)
 
I like Serena said:
Does it compile? (Wondering)

I don't think so... (Sweating)



I like Serena said:
How many registers do you count that would be needed, counting the things we can? (Wondering)

How can we count how many registers are needed? (Worried)
 
  • #10
evinda said:
I don't think so... (Sweating)

Then what's going wrong? (Wondering)
How can we count how many registers are needed? (Worried)

We need 1 register to keep the value of the parameter S.
It's not clear how many registers we need for x. That depends on how much information the type [m]info[/m] holds, but can say for now that it is sizeof(info).
Then we call 2 functions that would again take the parameter S.
Those 2 functions probably don't need anything else, so that is 1 more register.
If we ignore the stack frame and return address, that makes for a total of:
$$1 + \text{sizeof}(info) + 1 = \text{sizeof}(info) + 2$$
(Mmm)
 
  • #11
I like Serena said:
Then what's going wrong? (Wondering)

We need 1 register to keep the value of the parameter S.
It's not clear how many registers we need for x. That depends on how much information the type [m]info[/m] holds, but can say for now that it is sizeof(info).
Then we call 2 functions that would again take the parameter S.
Those 2 functions probably don't need anything else, so that is 1 more register.
If we ignore the stack frame and return address, that makes for a total of:
$$1 + \text{sizeof}(info) + 1 = \text{sizeof}(info) + 2$$
(Mmm)

We use three times the value of the parameter S, right? (Thinking)

So, shouldn't it be $\text{sizeof}(info) + 3$?

Or have I understood it wrong? (Worried)
 
  • #12
evinda said:
We use three times the value of the parameter S, right? (Thinking)

So, shouldn't it be $\text{sizeof}(info) + 3$?

Or have I understood it wrong? (Worried)

The first time we're getting S as an input parameter, which takes up 1 register.
The second time, we use S to call IsStackEmpty(S), which takes up another register (although this could be optimized away).
After that we don't need this 2nd register anymore and we can reuse it.
Then, the third time, in the call to Top(S), we can reuse the 2nd register to pass S as a parameter. (Nerd)

Actually, Top(S) would keep x as a local variable before returning it, which would take another $\text{sizeof}(info)$, although that can be optimized away as well. (Thinking)

But to keep things clean we would get: $2\text{ sizeof}(info) + 2$ (excluding stack frame and return address). (Mmm)
 

Similar threads

  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 7 ·
Replies
7
Views
3K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 7 ·
Replies
7
Views
2K
  • · Replies 8 ·
Replies
8
Views
5K
  • · Replies 3 ·
Replies
3
Views
1K
  • · Replies 3 ·
Replies
3
Views
6K
  • · Replies 17 ·
Replies
17
Views
2K
  • · Replies 23 ·
Replies
23
Views
2K
  • · Replies 7 ·
Replies
7
Views
2K