stack.h
#define MAX_STACK 10
typedef int STACK_ITEM;
typedef struct Stack *STACK ;
stack.c
#include"stack.h"
struct Stack{
STACK_ITEM contents[MAX_STACK];
int tos;
};
_Bool create_stack(STACK s){
s = malloc(sizeof(struct Stack));
if(s == NULL )
return 0;
s->tos = 0;
return 1;
}
When calling the create_stack function, it doesn't affect s (pointer to structure) at all. So, my question is: why is s not changing, even though it is a pointer, not a value, passed?
Remember, all parameters are passed by value in C.
When you pass a pointer as a function parameter, you can access the object (or array of objects) pointed to by that pointer.
Your create_stack() is passed a pointer to a struct Stack, that is the s parameter. It then ignores the original value of s and reassigns it. That is allowed, but note that it does not change the original pointer in the caller of create_stack() because function parameters are passed by value.
There are two ways to do what you want.
The first way is to pass a pointer to a pointer:
_Bool create_stack(STACK *s){
*s = malloc(sizeof(struct Stack));
if(*s == NULL )
return 0;
(*s)->tos = 0;
return 1;
}
Call it e.g.:
STACK mystack;
_Bool ret;
ret = create_stack(&mystack);
if (!ret) {
/* error */
}
The second way is to not pass anything and return a pointer to the allocated stack:
STACK create_stack(void){
STACK s = malloc(sizeof(struct Stack));
if(s != NULL ) {
s->tos = 0;
}
return s;
}
Call it e.g.:
STACK s;
s = create_stack();
if (s == NULL) {
/* error */
}
Finally, as a point of programming style, do not typedef pointers in the way you have done. It is clearer if the pointer is explicit, for example, use typedef struct Stack STACK; instead of typedef struct Stack *STACK; and adjust the usage accordingly, for example, replacing STACK s with STACK *s and replacing STACK *s with STACK **s.
Function parameters are its local variables. That is the parameters hold copies of the passed arguments. To change an original argument in a function you have to pass it by reference through pointer.
So change the function like
_Bool create_stack(STACK *s){
*s = malloc(sizeof(struct Stack));
if(*s == NULL )
return 0;
( *s )->tos = 0;
return 1;
}
In order for a C function to modify an argument, the argument must be given as a pointer to the value to be changed. Thus, for a simple integer argument:
void Inc(int *value) {
++(*value);
}
will do the trick, but:
void Inc(int value) {
++value;
}
will do absolutely nothing to any argument given in a call to Inc, as the function just gets a copy of the 'value' given.
The same goes for a pointer! Your function just changes a copy of the pointer it is passed. So, you should change your function to take a pointer to the pointer:
_Bool create_stack(STACK *s){ // Pointer to a pointer to Stack
*s = malloc(sizeof(struct Stack)); // Change the value of the STACK object pointed to
if (*s == NULL )
return 0;
(*s)->tos = 0; // And, again, we need to (singly) dereference to 'double' pointer
return 1;
}
Then, in your calling code, where you originally have something like:
_Bool answer = create_stack(myStackPointer);
you would need to add the address of your pointer:
_Bool answer = create_stack(&myStackPointer);
Feel free to ask for further clarification and/or explanation.
Related
first time posting here, any help would be appreciated. I'm trying to change the value "size" inside my stack called "try", by putting it through my function called Stack_Init. If I print out the value of "stack->size" inside the function, it gives me the correct value for size (being 4). If I were to print
try->size after executing my function (at the end of the code), it would give me a value of 0.
struct intnode {
int data;
struct intnode *next;
}; typedef struct intnode node;
struct stack {
node *top;
int size;
}; typedef struct stack Stack;
void Stack_Init(Stack *S, int size){
Stack *stack = malloc(size*sizeof(node));
stack->top = NULL;
stack->size = size;//for some reason, this doesn't change try->size
}
int main(){
Stack *try;
int size = 4;
Stack_Init(try,size);
printf("%d %d ", try->size, try->top);
Thanks for reading!
You are trying to change a pointer that you pass to the function, so you need an extra level of indirection, i.e. a pointer to pointer. In addition, you need to assign to dereferenced parameter instead of a local variable:
void Stack_Init(Stack **S, int size){
// ^
// |
// Extra asterisk here
*S = malloc(size*sizeof(node));
// ^
// |
// Dereference the pointer passed into the function
(*S)->top = NULL;
(*S)->size = size;
}
The call to the function needs to look like this:
Stack_Init(&try,size);
// ^
// |
// Pass a pointer to a pointer
Your Stack_Init function has a couple problems with it. You are modifying a local variable instead of the argument passed to the function, and you're assigning the memory incorrectly. Try this instead.
void Stack_Init(Stack **S,int size) {
Stack *stack = (Stack*)malloc(sizeof(Stack));
stack->top = NULL;
stack->size = size;
*S = stack;
}
In this code I pass struct stack * sp as call by value ,if it pass by value approach then how it gets update the value in functions and if I miss something then help this to find out?
#include<stdio.h>
#include<conio.h>
struct stack{
int size ;
int top;
int * arr;
};//creating structures
void traversal(struct stack *sp){
for(int i=0;i<=sp->top;i++){
printf("%d\n",sp->arr[i]);
}
}
int isEmpty(struct stack* ptr){
if(ptr->top == -1){
return 1;
}
else{
return 0;
}
}
int isFull(struct stack* ptr){
if(ptr->top == ptr->size - 1){
return 1;
}
else{
return 0;
}
}
void push(struct stack* ptr, int val){
if(isFull(ptr)){
printf("Stack Overflow! Cannot push %d to the stack\n", val);
}
else{
ptr->top=ptr->top+1;//how it gets update when i pass by value
ptr->arr[ptr->top] = val;
}
}
int pop(struct stack* ptr){
if(isEmpty(ptr)){
printf("Stack Underflow! Cannot pop from the stack\n");
return -1;
}
else{
int val = ptr->arr[ptr->top];
ptr->top=ptr->top-1;//ptr pass by value how it gets update
return val;
}
}
int main(){
**struct stack *sp** = (struct stack *) malloc(sizeof(struct stack));//local pointer variable
sp->size = 10;
sp->top = -1;
sp->arr = (int *) malloc(sp->size * sizeof(int));
printf("Stack has been created successfully\n");
push(sp,10);//pass by value in push
push(sp,200);//pass by value in push
traversal(sp);
printf("the %d element from stack is popped\n",pop(sp));
printf("the %d element from stack is popped\n",pop(sp));
traversal(sp);
return 0;
}
Now in this code push and pop modify the top and array as I say I passed as a call by value as you see but they are also get modified in the above code but how?
Your code seems to contain some errors so let me address those first:
in the main() function you have declared this **struct stack *sp** = (struct stack *) malloc(sizeof(struct stack)). this is wrong and will bring up a error. You seem to want to pass sp by value, the correct way to declare sp would be to do struct stack *sp = (struct stack *) malloc(sizeof(struct stack)).
You seem to be mainly confused on how the struct that sp points to is being modified by the functions that you have made to implement a stack, lets go through main() and see what happends.
main():
int main(){
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));//local pointer variable
sp->size = 10;
sp->top = -1;
sp->arr = (int *) malloc(sp->size * sizeof(int));
printf("Stack has been created successfully\n");
push(sp,10);//pass by value in push
push(sp,200);//pass by value in push
traversal(sp);
printf("the %d element from stack is popped\n",pop(sp));
printf("the %d element from stack is popped\n",pop(sp));
traversal(sp);
return 0;
}
So i will break down how this works:
First of all in main() we have a pointer to a struct of type struct stack:
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));
This struct has some memory allocated for it and, sp stores the address of this struct.
Next in main() you store 10 in the member called size in the struct that sp points to:
sp->size = 10;
You also store -1 in the member called top in the struct that sp points to:
sp->top = -1;
Lastly you allocate some memory for the stack in this line, in this case you allocate 40 bytes for 10 ints:
sp->arr = (int *) malloc(sp->size * sizeof(int));
Now moving to the function calls:
you wrote push(sp,10)
lets break this down further and take a look at push()
push():
void push(struct stack* ptr, int val){
if(isFull(ptr)){
printf("Stack Overflow! Cannot push %d to the stack\n", val);
}
else{
ptr->top=ptr->top+1;//how it gets update when i pass by value
ptr->arr[ptr->top] = val;
}
}
push() takes 2 parameters, one is a pointer to a struct, the second is a integer value.
push(sp,10)
Now you pass sp to the first parameter struct stack* ptr, remember sp holds the address of a struct that you allocated memory for in main().
you are now giving this address to struct stack* ptr which is a local pointer to the push() function. After push() ends, struct stack* ptr will get destroyed.
With this in mind you are passing sp by value since you are not actually passing sp itself (address of sp), you are passing the address that sp is pointing to/holding into a copy which would be struct stack* ptr.
And now since you pass the address of the struct that sp is holding/pointing too, this address can be modified.
I'm doing an exercise, and want support about it. The problem is this: I have two structures (1 for the nodes of the stack, 1 for the stack). In the node structure, there is a void* data field.
I've tried to push a value on the stack but, because of void* data instead of simple data, I failed.
This is the code about the structures and the push() function.
struct upo_stack_node_s
{
void *data;
struct upo_stack_node_s *next;
};
typedef struct upo_stack_node_s upo_stack_node_t;
struct upo_stack_s
{
upo_stack_node_t *top;
size_t size;
};
/*Function for create the stack*/
upo_stack_t upo_stack_create()
{
upo_stack_t stack = malloc(sizeof(struct upo_stack_s));
if (stack == NULL)
{
fprintf(stderr, "Unable to create a stack!\n");
abort();
}
stack->top = NULL;
stack->size = 0;
return stack;
}
/*Push() function:*/
void upo_stack_push(upo_stack_t stack, void *data)
{
/* TO STUDENTS:
* Remove the following two lines and put here your implementation
*/
upo_stack_node_t *node = malloc(sizeof(struct upo_stack_node_s));
node->data = data; /*<-- Here's the problem */
node->next = stack->top;
stack->top = node;
++stack->size;
}
/*Top() function*/
void* upo_stack_top(const upo_stack_t stack)
{
/* TO STUDENTS:
* Remove the following two lines and put here your implementation
*/
return (void *)(stack->top); //<---
}
/*Function for testing (there are other functions in the code)*/
void test_top()
{
int value1 = 1;
int value2 = 2;
upo_stack_t stack;
stack = upo_stack_create();
upo_stack_push(stack, &value1); //<----
upo_stack_push(stack, &value2); //<----
assert( upo_stack_top(stack) != NULL );
assert( *((int*) upo_stack_top(stack)) == value2 ); <-- Here's the error
upo_stack_pop(stack, 0);
assert( upo_stack_top(stack) != NULL );
assert( *((int*) upo_stack_top(stack)) == value1 );
upo_stack_pop(stack, 0);
assert( upo_stack_top(stack) == NULL );
upo_stack_destroy(stack, 0);
}
You always have to pass a void pointer. That means if you want to pass a simple value, like 1, what you need to do is, is to allocate an integer value, and pass the pointer to it (as a void pointer).
Thus something like:
int x = 4;
upo_stack_push(upo_stack, &x);
Of course you have to make sure the int variable x does not go out of scope, otherwise the pointer will point to freed memory, which results in nasty memory problems.
Update
It is assumed above, that the void pointer you pass is stored already in memory for the scope of the stack. In case, you want the stack itself to copy the data, you have also to malloc space for that, thus not only mallocing the node, but also mallocing and copy the data type passed. Also to know the size of the data (since it is a void pointer, which is unaware of its type), you have to add an int size parameter to the push function.
For an integer value to be stored, pass it as a pointer, with size: sizeof(int). Than for copying the data structure, use memcpy. This only works for simple types and structures without pointers. If you have to copy structures with pointers (thus you need so called deep-copying), than it is more tricky.
first time posting here, any help would be appreciated. I'm trying to change the value "size" inside my stack called "try", by putting it through my function called Stack_Init. If I print out the value of "stack->size" inside the function, it gives me the correct value for size (being 4). If I were to print
try->size after executing my function (at the end of the code), it would give me a value of 0.
struct intnode {
int data;
struct intnode *next;
}; typedef struct intnode node;
struct stack {
node *top;
int size;
}; typedef struct stack Stack;
void Stack_Init(Stack *S, int size){
Stack *stack = malloc(size*sizeof(node));
stack->top = NULL;
stack->size = size;//for some reason, this doesn't change try->size
}
int main(){
Stack *try;
int size = 4;
Stack_Init(try,size);
printf("%d %d ", try->size, try->top);
Thanks for reading!
You are trying to change a pointer that you pass to the function, so you need an extra level of indirection, i.e. a pointer to pointer. In addition, you need to assign to dereferenced parameter instead of a local variable:
void Stack_Init(Stack **S, int size){
// ^
// |
// Extra asterisk here
*S = malloc(size*sizeof(node));
// ^
// |
// Dereference the pointer passed into the function
(*S)->top = NULL;
(*S)->size = size;
}
The call to the function needs to look like this:
Stack_Init(&try,size);
// ^
// |
// Pass a pointer to a pointer
Your Stack_Init function has a couple problems with it. You are modifying a local variable instead of the argument passed to the function, and you're assigning the memory incorrectly. Try this instead.
void Stack_Init(Stack **S,int size) {
Stack *stack = (Stack*)malloc(sizeof(Stack));
stack->top = NULL;
stack->size = size;
*S = stack;
}
I'm trying to implement a Queue in C (using a Linked List) to store pointers to data. The en-queuing seems to be working fine, but some trouble with pointers upon de-queuing.
In my main():
void* data = malloc(sizeof(int));
dequeue(&Q, data);
printf("(%d) %d\n", k, *(int*)data);
dequeue():
int dequeue(struct queue *q, void *value)
{
struct queue_node *tmp;
if (!q->first) {
value = 0;
return 1;
}
value = q->first->data;
tmp = q->first;
if (q->first == q->last)
q->first = q->last = NULL;
else
q->first = q->first->next;
free(tmp);
return 0;
}
Based on my debugging, it seems that the value of the *data pointer in the main() for loop doesn't retain the value that it's set to in dequeue(). What am I missing?
Edit:
struct queue_node
{
struct queue_node *next;
void* data;
};
struct queue
{
struct queue_node *first;
struct queue_node *last;
};
The queue_node's data holds a pointer to some value (here it is an int, but it may not be true always, otherwise you'd use an int instead...)
Since this value was allocated with malloc (and is not a local variable) you need to also free it at some point.
So, change the function's signature to accept a void**, don't allocate space for an int in main() but call dequeue with &data as a parameter, where void * data = 0. Don't forget to free data when done.
In dequeue, set *value = q->first->data.
You're setting the value of the "value" variable, which is a pointer local to the function.
If you want to set the value to which it points, use:
*value = 0;
and:
*value = q->first->data;
Edit (after question edit): Since queue_node.data is itself a pointer, it makes more sense to pass a void**, as #Andrei notes above.
Assuming data is a (void *) and you want the (int) value pointed to by data, you'll have to replace
value = q->first->data;
with
*(int *)value = *(int *)q->first->data;
in the function deque();