临时为算术运算void*的正确方法是什么?

Sam*_*amy 9 c valgrind void-pointers memcpy pointer-arithmetic

我是C新手,但多年来一直是程序员,所以我试图从2008年开始沿着斯坦福大学的课程学习C,并在C.中的向量上做作业3.

它基本上只是一个通用数组,所以数据作为一个结构保存在一个结构中void *.编译器标志-Wpointer-arith打开,所以我不能算术(我明白原因).

数据周围的结构必须不知道数据的类型,因此它对调用者来说是通用的.

为简化起见,我正在尝试以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    void *data;
    int aindex;
    int elemSize;
} trial;

void init(trial *vector, int elemSize)
{
    vector->aindex = 0;
    vector->elemSize = elemSize;
    vector->data = malloc(10 * elemSize);
}

void add(trial *vector, const void *elemAddr)
{
    if (vector->aindex != 0)
        vector->data = (char *)vector->data + vector->elemSize;

    vector->aindex++;
    memcpy(vector->data, elemAddr, sizeof(int));

}

int main()
{
    trial vector;
    init(&vector, sizeof(int));

    for (int i = 0; i < 8; i++)
        {add(&vector, &i);}

    vector.data = (char *)vector.data - ( 5 * vector.elemSize);
    printf("%d\n", *(int *)vector.data);
    printf("%s\n", "done..");

    free(vector.data);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是我免费得到一个错误free(): invalid pointer.所以我跑valgrind了它并收到以下内容:

==21006==  Address 0x51f0048 is 8 bytes inside a block of size 40 alloc'd
==21006==    at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==21006==    by 0x1087AA: init (pointer_arithm.c:13)
==21006==    by 0x108826: main (pointer_arithm.c:29)
Run Code Online (Sandbox Code Playgroud)

此时我的猜测是我要么做得不char*正确,要么使用memcpy 不正确

das*_*ght 10

发生这种情况是因为您向向量添加了8个元素,然后在尝试使用之前仅将指针"回滚"了五步free.您可以通过使用vector->aindex来决定展开索引的数量来轻松解决这个问题.

然而,问题的根本原因是您要修改vector->data.您应该首先避免修改它,add而是依赖于函数内部的临时指针:

void add(trial *vector, const void *elemAddr, size_t sz) {
    char *base = vector->data;
    memcpy(base + vector->aindex*sz, elemAddr, sz);
    vector->aindex++;
}
Run Code Online (Sandbox Code Playgroud)

注意使用sz,你需要传递sizeof(int)给它.

在你的代码的另一个问题是,当你通过铸造打印vector.dataint*.这可能会奏效,但更好的方法是编写类似的read函数来提取数据.