Reputation: 25
#define MAX_STACK 10
typedef int STACK_ITEM;
typedef struct Stack *STACK ;
#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?
Upvotes: 1
Views: 87
Reputation: 17503
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
.
Upvotes: 1
Reputation: 51874
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.
Upvotes: 1
Reputation: 311078
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;
}
Upvotes: 1