Home > database >  Using realloc to expand vector of structures in c
Using realloc to expand vector of structures in c

Time:12-02

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