假设你在一个 x64 环境中打包但没有对齐,那么sizeof( struct node ) == 20 因为8 + 8 + 4 == 20:
sizeof( struct example* ) == 8 // Remember this struct member is a pointer, not a value
sizeof( struct example* ) == 8 // Ditto
sizeof( int ) == 4 // `int` is usually 4 bytes
这个 malloc 实际上是做什么的?我知道它应该分配内存,以便 example_node 可以指向某个地址,该地址包含足够用于整个结构节点的字节
这是正确的。
在典型的桌面操作系统的用户空间中,您的代码将在进程的内存空间中运行。内存(通常)以操作系统提供的称为“页面”的大块的形式出现,C 运行时的malloc 将请求这些页面,然后管理这些页面内的数据分配。
在桌面操作系统环境中,malloc( 20 ) 执行如下操作:
- 可用页面中是否有足够的空间容纳连续的 20 个字节?
- 是吗?然后使用我们的内部内存映射找到一个连续的 20 字节区域,并返回该区域第一个字节的地址。
- 没有?然后向操作系统请求一个新页面,将其添加到我们的内部内存映射中,并返回该新页面中某个区域的地址
a) 是否有足够的空间来启动结构的空白模板
简短回答:是的 - 因为你做了malloc( sizeof( struct node ) ),然而 malloc 可能会失败(在这种情况下,它会返回 NULL (0),重要的是你在之后检查这个每次分配。这可能是由于内存不足、碎片过多等造成的。
struct node *example_node = malloc(sizeof(struct node));
if( !example_node ) {
puts( "Allocation failed. Exiting." );
exit( 1 );
}
b) 结构节点内部的两个结构是否也已启动?那么我可以开始做类似 example_node->left->foo 的事情了吗?
没有。这些成员是指针。您需要自己初始化它们。您可以通过进一步调用malloc 或将它们分配给内存中其他现有的struct node 对象来初始化它们。
c) left 和 right 的结构示例 *foo 是否也已启动?
没有。看我上面的答案。
您的 struct node 和 struct example 案例可以无限递归地填充 - 走多远取决于您。
创建一个 3 个节点深的简单二叉树:
struct node* allocateNode() {
struct node* newNode = malloc( sizeof( struct node ) );
if( !newNode ) exit( 1 ); // fast-fail
newNode.left = NULL; // zero-out the pointer members because `malloc` does not zero out memory for you!
newNode.right = NULL;
return newNode;
}
void initializeNode( struct node* parent ) {
parent.left = malloc( sizeof( struct node ) );
parent.right = malloc( sizeof( struct node ) );
}
void createTree( struct node* parent, int depth ) {
if( depth <= 0 ) return NULL;
parent.left = allocateNode();
createTree( parent.left, depth - 1 );
parent.right = allocateNode();
createTree( parent.right, depth - 1 );
}
void destroyTree( struct node* node ) {
if( node == NULL ) return;
destroyTree( node.left );
destroyTree( node.right );
free( node );
}
int main( int argc, char* argv[] ) {
struct node* root = allocateNode();
createTree( root, 3 );
// (do stuff here)
destroyTree( root );
return 0;
}
我注意到您可以通过使用calloc 并一次分配所有节点来更有效地做到这一点:
int main( int argc, char* argv[] ) {
const size_t n = 7; // a tree 3 layers deep has 7 nodes: 1, 2L, 2R, 3LL, 3LR, 3RL, 3RR
struct node[] allNodes = calloc( n, sizeof(struct node) );
if( !allNodes ) exit( 1 );
// Binary heap array representation algorithm:
size_t lastParent = 3;
for( size_t i = 0; i < n; i++ ) {
if( i < lastParent ) {
allNodes[i].left = allNodes[ ( 2 * i ) + 1 ];
allNodes[i].right = allNodes[ ( 2 * i ) + 2 ];
}
else {
allNodes[i].left = NULL;
allNodes[i].right = NULL;
}
}
return 0;
}
重要提示!!!!!!11111!
永远不要忘记为每次成功的malloc 或calloc 呼叫拨打free!否则会泄露内存!