C语言 尝试从结构的动态数组中移除元素时出现分段错误

6ojccjat  于 2023-02-07  发布在  其他
关注(0)|答案(1)|浏览(127)

我试图从一个结构体动态数组中删除一个元素,方法是将每个结构体向左移动,然后将数组重新分配为小一个的大小。

我的问题是:*(p[i])=*(p[i]+1);(*p)[i]=(*p)[i+1];有什么区别,为什么第二个代码可以工作而第一个代码不能工作,导致分段错误。

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

qij5mzcb1#

作为struct **p,表达式(*p)[i]首先引用(*p)(*p)是位于数组开头的(struct event *),并且[i]解引用索引i

(*p): (struct events *) 0x5555555592a0
(*p)[1]: (struct events *) 0x5555555592a4

相反,*(p[i])将遵从p之后存储的i * sizeof(struct events**)字节,然后再次遵从*(...)

p: (struct events **) 0x7fffffffde68
p+1: (struct events **) 0x7fffffffde70
p[1]: (struct events **) 0x7fffffffdf70

这些地址来自同一个运行,顺便说一句,*p是通过malloc()从堆返回的内存地址,而p是传递参数的堆栈上的地址。
这里是memmove的实现,顺便说一句,你应该向调用者报告一个错误,否则他们不知道数组的正确大小。还将len参数移到了第一位,以表达plen之间的关系:

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

相关问题