C struct and malloc problem (C)

2019-04-09 13:09发布

问题:

It's amazing how even the littlest program can cause so much trouble in C.

#include <stdio.h> 
#include <stdlib.h> 

typedef struct node {
    int value;
    struct node *leftChild;
    struct node *rightChild;
} node;

typedef struct tree {
    int numNodes;
    struct node** nodes;
} tree;

tree *initTree() {
    tree* tree = (tree*) malloc(sizeof(tree));
    node *node = (node*) malloc(sizeof(node));
    tree->nodes[0] = node;
    return tree;
}

int main() {
    return 0;
}

The compiler says:

main.c: In function 'initTree':
main.c:17: error: expected expression before ')' token 
main.c:18: error: expected expression before ')' token

Can you please help?

回答1:

You're using two variables named tree and node, but you also have structs typedefed as tree and node.

Change your variable names:

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int value;
    struct node *leftChild;
    struct node *rightChild;
} node;

typedef struct tree {
    int numNodes;
    struct node** nodes;
} tree;

tree *initTree() {
   /* in C code (not C++), don't have to cast malloc's return pointer, it's implicitly converted from void* */
   tree* atree = malloc(sizeof(tree)); /* different names for variables */
   node* anode = malloc(sizeof(node));
   atree->nodes[0] = anode;
   return atree;
}

int main() {
    return 0;
}


回答2:

tree and node is your case are type names and should not be used as variable names later on.

tree *initTree() {
    tree *myTree = (tree*) malloc(sizeof(tree));
    node *myNode = (node*) malloc(sizeof(node));
    myTree->nodes[0] = myNode;
    return myTree;
}


回答3:

Change (tree*) and (node*) to (struct tree*) and (struct node*). You can't just say tree because that's also a variable.



回答4:

Change the body of initTree as follows:

tree* myTree = (tree *)malloc(sizeof(tree));
node *myNode = (node *)malloc(sizeof(node));
myTree->nodes[0] = myNode;
return myTree;


回答5:

Don't use typedef'ed names as variable names, and there is not need to cast malloc(); in C.

#include <stdio.h> 
#include <stdlib.h> 

typedef struct node {
    int value;
    struct node *leftChild;
    struct node *rightChild;
} node;

typedef struct tree {
    int numNodes;
    struct node** nodes;
} tree;

tree *initTree() {
    tree->nodes[0] = malloc(sizeof(node));
    return malloc(sizeof(tree));
}

int main() {
    return 0;
}


回答6:

I second that Mehrdad's explanation is to the point.

It's not uncommon that in C code you define a variable with the same name as the struct name for instance "node node;". Maybe it is not a good style; it is common in, e.g. linux kernel, code.

The real problem in the original code is that the compiler doesn't know how to interpret "tree" in "(tree*) malloc". According to the compiling error, it is obviously interpreted as a variable.



回答7:

Apart from the original question, this code, even in it's correct forms will not work, simply due to the fact that tree::nodes (sorry for the C++ notation) as a pointer to a pointer will not point to anything usefull right after a tree as been malloced. So tree->nodes[0] which in the case of ordinary pointers is essentially the same like *(tree->nodes), can't be dereferenced. This is a very strange head for a tree anyway, but you should at least allocate a single node* to initialize that pointer to pointer:

tree *initTree() {
   /* in C code (not C++), don't have to cast malloc's return pointer, it's implicitly converted from void* */
   tree* atree = malloc(sizeof(struct tree)); /* different names for variables */

   /* ... */

   /* allocate space for numNodes node*, yet numNodes needs to be set to something beforehand */
   atree->nodes = malloc(sizeof(struct node*) * atree->numNodes);

   node* anode = malloc(sizeof(struct node));
   atree->nodes[0] = anode;
   return atree;
}


回答8:

Interestingly, it does compile cleanly if you simply write the allocations as:

tree *tree = malloc( sizeof *tree );

It is often considered better style to use "sizeof variable" rather than "sizeof( type )", and in this case the stylistic convention resolves the syntax error. Personally, I think this example is a good case demonstrating why typecasts are generally a bad idea, as the code is much less obfuscated if written:

struct tree *tree = malloc( sizeof *tree );


标签: c struct malloc