C/C++对一块内存进行malloc,然后对不同的任意类型使用不同的部分
C/C++ malloc a block of memory and then use different portion for different, arbitrary types
我肯定没有什么理由这么做。就说我很无聊,想探索一下这是否可能。:)
假设我想实现一个链表的节点。我当然可以做
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+1
和first + 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:不要这样做
要补充其他人所说的内容,您也不能假设结构的大小与其字段大小之和相同。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 这是我尝试让用户将值输入到数组中.然后将其隐藏为大量的星号
- boost::asio如何生成多个协同程序,然后加入它们
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 在std::thread中,joinable()然后join()线程安全吗
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- C++:如何读取分离变量,然后读取向量
- 从函数返回任意简单类型的数据
- 为什么我的递归函数按降序打印,然后按升序打印?
- 等待整个 omp 块完成,然后再调用第二个函数
- CMake:如何将库 A 链接到库 B,然后将可执行文件链接到库 A
- 如何生成一个随机的 n 位数,其中 n 是任意的
- 如何存储用户输入的所有数据,然后在他们想要查看所有数据时显示它们
- '{'标记之前的预期类名,然后在预声明时无效使用不完整的类型'class class_name'
- 如何使变量从 x 到 y,然后从 y 返回到 x 并始终重复该过程
- 如何在给定任意数量的整数的情况下创建一个唯一键?并使用该键存储,然后从地图中查找
- 将具有任意参数和占位符的函数存储在类中,然后再调用它
- C/C++对一块内存进行malloc,然后对不同的任意类型使用不同的部分
- 复制构造,然后访问任意POD类型