c - 如何在内存块的任意位置插入一个值?

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

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

最佳答案

更新:

有两个问题,都在对 memmove 的调用中。

第一个是应移动的字节数中存在一个离一错误。正确的数字是:

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

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

第二个问题更大,但更微妙。将整数添加到指针会导致编译器执行 pointer arithmetic ,它自动考虑所指向对象的大小。请参阅this question了解详情。这是简短的版本:self->items 是一个 OBJ 数组,因此您不需要在memmove 的前两个参数。

把它们放在一起,正确的函数调用如下所示:

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

关于c - 如何在内存块的任意位置插入一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3173129/

相关文章:

c - 我应该#include 什么来使用 'htonl' ?

linux - 是否可以延迟 Linux OOM Killer 并运行我的进程?

ruby-on-rails - Redis 在大型 DEL 和 HMSET 函数上消耗最大内存

java - 我想找到图像的坐标

c++ - 按地址从 vector 中删除一个元素

c++ - 通过引用传递参数时,可以将 & 号 "&"放在哪里?

c++ - GDB 无法访问 mmap() 的内核分配内存?

c++ - 逗号运算符和赋值运算符 - 返回值

C 数学和零结果

c - C 结构体的总大小