Reputation: 31
I am trying to remove an element from an dynamic array of structs by moving each struct to the left then reallocating my array one size smaller.
My question is: what is the difference between *(p[i])=*(p[i]+1);
and (*p)[i]=(*p)[i+1];
, and why does the second one works whilst the first code does not, resulting in segmentation fault.
void rm_event(struct events **p, int index, int qtty){
for(int i=index; i<qtty-1; i++){
*(p[i])=*(p[i]+1); // (*p)[i]=(*p)[i+1];
}
struct events *tmp;
tmp=(struct events*)realloc(*p, sizeof(struct events)*(qtty-1));
if(tmp!=NULL)
*p=tmp;
}
Upvotes: 0
Views: 90
Reputation:
As struct **p
the expression (*p)[i]
first references (*p)
which is a (struct event *)
at the start of you array and [i]
dereference index i
:
(*p): (struct events *) 0x5555555592a0
(*p)[1]: (struct events *) 0x5555555592a4
In contrast *(p[i])
will deference whatever is stored i * sizeof(struct events**)
bytes after p
then deference that again with *(...)
. Either dereference may trigger a segfault:
p: (struct events **) 0x7fffffffde68
p+1: (struct events **) 0x7fffffffde70
p[1]: (struct events **) 0x7fffffffdf70
These addresses are from the same run, btw, *p
is the address of the memory returned from the heap via malloc()
while p
is address on the stack where the argument is being passed.
Here's the memmove implementation, btw, and you should report an error back to caller otherwise they don't know the correct size of the array. Also moved the len
argument first to express how p
and len
are related:
void rm_event(size_t len, struct events *p[len], size_t index) {
if(!p || *p || index >= len || !len)
return;
memmove(&(*p)[index], &(*p)[index+1], (len - index - 1) * sizeof **p);
struct events *tmp;
tmp = realloc(*p, sizeof(struct events)*(len - 1));
if(!tmp)
return;
*p=tmp;
}
Upvotes: 1