简体   繁体   中英

single malloc for creating 2 structs

I have a node with this structure:

struct node
{
    unsigned long key;
    unsigned long value;
    struct node* lChild;    
    struct node* rChild;   
};

I have a dummy node which has default values:

struct node* newSpecialNode()
{
    struct node* node = (struct node*) malloc(sizeof(struct node));
    node->key = 0;
    node->value = 0;
    node->lChild = NULL;
    node->rChild = NULL;
    return(node);
}

All nodes in my data structure will call this method to create a node.

struct node* newInternalNode(unsigned long key, unsigned long value)
{
    struct node* node = (struct node*) malloc(sizeof(struct node));
    node->key = key;
    node->value = value;
    node->lChild = newSpecialNode();
    node->rChild = newSpecialNode();
    return(node);
}

I call the function newSpecialNode() for left and right child. So there are two malloc calls. But whenever I create a node, I always create two dummy nodes. So I wanted to do a single malloc which allocates memory for both lChild and rChild . Possibly allocate a double word and reference its parts. But I do not know how to do it.

I tried this approach. But again I need to do two mallocs.

struct node** ptrToTwoNodes = (struct node**) malloc(2*sizeof(struct node*));
ptrToTwoNodes[0] = (struct node*) malloc(sizeof(struct node));
ptrToTwoNodes[1] = (struct node*) malloc(sizeof(struct node));

While you technically can allocate all three nodes with a single malloc() , you really shouldn't because it breaks the recursive "symmetry" of the tree structure.

When calling malloc() three times, you get a tree where each node is independent of each other. That means you can change the tree later (adding and removing nodes) without having to worry how the child node was allocated.

The root of the problem is that you can't free() part of a memory segment returned my malloc() . You always have to call free() exactly once for each pointer returned by malloc() - no more and no less.

If malloc is too expensive for you, then an alternative is to create a set of helper functions that keep a pool of node structures (so they allocate N at once and then return one after the other until the pool runs out). See object pool pattern .

If you want to allocate a single block of memory for the two nodes, try

struct node* ptrToTwoNodes = (struct node*) malloc(2*sizeof(struct node));

then &ptrToTwoNodes[0] and &ptrToTwoNodes[1] will be pointers to your two nodes. BTW I guess you should remove C++ tag.

You can allocate memory for 2 nodes, and assign the pointer to a variable:

struct node* ptrToTwoNodes = (struct node*) malloc(2*sizeof(struct node));
ptrToTwoNodes[0].value = ...;
ptrToTwoNodes[1].value = ...;

I am not sure what is your end result, but you can do it like:

struct node
{
    unsigned long key;
    unsigned long value;
    struct node* Child;    //allocate two 2 node sized blocks for it & access left-Child[0], right-Child[1]
};

And Initialize as:

struct node* newSpecialNode()
{
    struct node* node = (struct node*) malloc(sizeof(struct node));
    node->key = 0;
    node->value = 0;
    node->Child = NULL;
    return(node);
}

And then allocate like:

struct node* newInternalNode(unsigned long key, unsigned long value)
{
    struct node* node = (struct node*) malloc(sizeof(struct node));
    node->key = key;
    node->value = value;
    node->Child = malloc(sizeof(sruct node)*2); //Child[0] & Child[1] 
    return(node);
}

Modify the code like follows:

struct node * newSpecialNode(void)
{
  struct node * node = malloc(2 * sizeof(*node));
  node->key = 0;
  node->value = 0;
  node->lChild = NULL;
  node->rChild = NULL;
  ++node;

  node->key = 0;
  node->value = 0;
  node->lChild = NULL;
  node->rChild = NULL;
  --node;

  return node;
}

struct node * newInternalNode(unsigned long key, unsigned long value)
{
  struct node * node = malloc(sizeof(*node));
  node->key = key;
  node->value = value;
  node->lChild = newSpecialNode();
  node->rChild = node->lChild + 1; 

  return node;
}

Take care on how to free() things.

Also add error checking to all those malloc() s.

Also^2: In C there is no need to cast the result of malloc() , nor is it recommended.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM