C / C ++ malloc一块内存然后使用不同的部分用于不同的任意类型

时间:2015-04-10 01:17:22

标签: c++ c malloc

我当然没有理由这样做。我们只是说我很无聊,想要探索是否可行。 :)

假设我想实现链表的节点。我当然可以做到

struct Node {
  int val; 
  Node *prev, *next; 
}

但是,让我说我很无聊,我想做一些事情,比如为一个节点malloc-ing一块内存,然后任意决定第一部分是指向前一个节点的指针,中间部分是值,最后一部分是指向下一个节点的指针。可以吗?

我尝试过类似的东西而且无法运行。

*second = first

具体失败。

void** createNewNode(int val) {
    void** p = (void**)malloc(sizeof(int) + 2*sizeof(void*));
    *(p+1) = &val; 
}

void connectTwoNodes(void** first, void** second) {
    *(first+2) = second; 
    cout << "first assigned!" << endl;
    *second = first;
    cout << "second assigned!" << endl;
}

int main() {

    void** p1 = createNewNode(1);
    void** p2 = createNewNode(2);
    cout << "both created!" << endl;
    connectTwoNodes(p1, p2);

    return 0;
}

2 个答案:

答案 0 :(得分:3)

嗯,一般的想法是可能的,但你的代码有很多错误:

  • p+1first + 2是非法的,因为您无法对void *进行点算术。在进行算术运算之前,必须将指针转换为指向完整类型。
  • *second是非法的,因为void是不完整的类型。
  • sizeof(void *)可能与sizeof(Node *)
  • 不同
  • 如果你打算写struct Node *ptr = p1;,那实际上由于结构填充而无效。同样,尝试通过转换地址来访问Node *指针可能会因对齐而失败。你必须memcpy指出存储的指针。

通常,您可以在malloc'空间中读取和写入任何符合对齐和严格别名规则的空格。转述,后者说如果你把一些东西写入内存,那么你就不能把它作为一种不同的类型读出来(除非那种不同的类型是一种字符类型)。但你可以覆盖它。

我无法弄清楚你在connectTwoNodes尝试做什么。但是在C中执行类似操作的代码可能是:

void *createNewNode(int val) 
{
    char *cp = malloc(sizeof(int) + 2 * sizeof(void *));
    void *null_node = NULL;

    memcpy(cp, &val, sizeof val);
    memcpy(cp + sizeof val, &null_node, sizeof null_node);
    memcpy(cp + sizeof val + sizeof null_node, &null_node, sizeof null_node);
    return cp;
}

void connectTwoNodes(void* first, void* second) 
{
    char *c1 = first, *c2 = second;

    // first->next = second
    memcpy(c1 + sizeof(int) + sizeof(void*), &second, sizeof second);

    // second->prev = first
    memcpy(c2 + sizeof(int), &first, sizeof first);
}

int main()
{
    void* p1 = createNewNode(1);
    void* p2 = createNewNode(2);
    connectTwoNodes(p1, p2);  
}

tl; dr:不要这样做

答案 1 :(得分:0)

要添加其他人所说的内容,您也不能假设结构的大小与其字段大小的总和相同。