开发者

C struct and malloc problem (C)

开发者 https://www.devze.com 2023-02-05 22:53 出处:网络
It\'s amazing how even the littlest program can cause so much trouble in C. #include <stdio.h>

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 befor开发者_如何学编程e ')' token 
main.c:18: error: expected expression before ')' token

Can you please help?


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


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


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


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;


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


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.


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


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 );
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号