I was trying to write a stack in C, but i had some problems regarding realloc. Finally i managed to write a working program but i don't get why does it work and why i have to give on the input of my functions put_on_fun_stack and get_from_fun_stack a pointer to my table of structures.
When i tried to give it like put_on_fun_stack(stack_t *s, ...) it didin't work. Why do i have to put pointer in realloc and why do i have to write a (*s)[*l], and i can't write *s[*l]. Can somebody please explain the pointers to structures?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int *n;
char *name;
}stack_t;
void init(stack_t **s){
*s=malloc(0);
}
void put_on_fun_stack(stack_t **s, char *name, int *l, int n){
*s = realloc(*s, (*l 1) * sizeof(stack_t));
(*s)[*l].name = name; //why do i need (*s) ?
(*s)[*l].n = n;
*l=*l 1;
}
char* get_from_fun_stack(stack_t **s, int *l){
char *temp = (*s)[*l-1].name;
*s = realloc(*s, (*l - 2) * sizeof(stack_t));
*l=*l-2;
return temp;
}
void rm(stack_t *s){
free(s);
}
int main(int argc, char **argv){
char *name;
stack_t* s;
init(&s);
int i;
int l=0;
srand(time(0));
if (argc>1)
for(i=1;i<argc;i ){
printf("%s\n", argv[i]);
put_on_fun_stack(&s, argv[i], &l, rand());
printf("name=%s, n=%d, l=%d \n", s[l-1].name,s[l-1].n, l-1);
}
rm(s);
return 0;
}
CodePudding user response:
C is pass by value so when you call put_on_fun_stack()
and you just pass s
you have a copy of main's value of s
and not the address of s
. You can't change the value of s
that's in main
. In other words, when you had it coded as s = realloc(s, (*l - 2) * sizeof(stack_t));
you're only changing the value of s
in put_on_fun_stack()
and it doesn't affect the s
from main
.
You fixed that by passing the address of s
in main to put_on_fun_stack()
and so as coded *s = realloc(*s, (*l - 2) * sizeof(stack_t));
the value of s
in main
gets set as you need it to.
As for (*s)[*l]
vs *s[*l]
, it's a matter of operator precedence. []
binds tighter than *
so *s[*l]
is the same as *(s[*l])
. Not what you want.
If your question is, why does (*s)[*l]
work you have to look at what s
is. s
is a stack_t **
, (*s)
then is a stack_t *
and (*s)[*l]
then is the *lth
element of the array pointed to by (*s)
.
Looking at why the other one doesn't work, (s[*l])
is the *lth
element of an array of stack_t *
and then *s(*l])
is the 0th element of the *lth
stack_t *
. It will only work when *l
is 0
.
It would be confusing but you can avoid the ()
by coding it as s[0][*l]
. A cleaner way to clean it up is to dereference s
and save it in a local variable, sort of like this:
void put_on_fun_stack(stack_t **ps, char *name, int *pl, int n){
stack_t *s;
int l=*pl;
s = realloc(*ps, (l 1) * sizeof(stack_t));
s[l].name = name;
s[l].n = n;
// return the updated values
*pl=l 1;
*ps=s;
}