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

C/C++ malloc a block of memory and then use different portion for different, arbitrary types

本文关键字:然后 任意 类型 C++ 内存 一块 malloc      更新时间:2023-10-16

我肯定没有什么理由这么做。就说我很无聊,想探索一下这是否可能。:)

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

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

但假设我很无聊,我想做一些事情,比如为一个节点对一块内存进行malloc,然后任意决定第一部分是指向前一个节点的指针,中间部分是值,最后部分是指向下一个节点。它能做到吗?

我试过这样的东西,但它没能运行。

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

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

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

通常,您可以根据对齐和严格的混叠规则在malloc'd空间中读写任何您喜欢的内容。后者说,如果你把一些东西写进记忆中,那么你就不能把它读成不同的类型(除非不同的类型是字符类型)。但是你可以覆盖它。

我不知道你在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:不要这样做

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