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;
}
