如何在内存块中的任意位置插入值?

时间:2010-07-03 23:03:43

标签: c memory pointers

我有两个C函数,它们基本上是在堆栈数据结构上运行的。这个将类型OBJ的值实际上只是unsigned long推送到堆栈的顶部。如有必要,堆栈也会增长。

OBJ Quotation_push_(CzState *cz, CzQuotation *self, OBJ object)
{
    if ((self->size + 1) > self->cap) {
        self->items = (OBJ *)CZ_REALLOC(self->items, sizeof(OBJ) * (self->cap + 1) * 2);
        self->cap = (self->cap + 1) * 2;
    }
    self->items[self->size++] = object;
    return (OBJ)self;
}

下一个函数将OBJ插入self->items数组中的任意位置。尽可能地尝试,它将无法正常工作。我在这里使用Quotation_push_使用虚拟值来获得自动增长行为。问题是我总是在数组的末尾看到CZ_NIL虚拟值,我试图插入的项目只是覆盖已经在位置的内容。这是我到目前为止所得到的:

OBJ Quotation_insert_(CzState *cz, CzQuotation *self, OBJ object, int pos)
{
    printf("have to move %d OBJ from %d to %d\n", self->size - pos, pos, pos + 1);
    Quotation_push_(cz, self, CZ_NIL);
    memmove(self->items + ((pos + 1) * sizeof(OBJ)), self->items + (pos * sizeof(OBJ)), sizeof(OBJ) * (self->size - pos));
    self->items[pos] = object;
    return (OBJ)self;
}

我没有收到任何段错误或错误,它只是没有按预期工作。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

<强> 更新

在致电memmove时,有两个问题。

第一个是应该移动的字节数的一个一个错误。正确的数字是:

sizeof(OBJ) * (self->size - pos - 1)

省略-1实际上会移动太多字节,将新的CZ_NIL对象放在缓冲区的末尾。

第二个问题更大,但更微妙。将整数添加到指针会导致编译器执行pointer arithmetic,这会自动计算所指向对象的大小。有关详细信息,请参阅this question。以下是简短版本:self->itemsOBJ的数组,因此您无需在sizeof(OBJ)的前两个参数中包含memmove

将所有内容放在一起,正确的函数调用将如下所示:

memmove((self->items + pos + 1),
        (self->items + pos),
        sizeof(OBJ) * (self->size - pos - 1));