C структура и проблема malloc (C) - PullRequest
4 голосов
/ 22 января 2011

Удивительно, как даже самая маленькая программа может вызвать столько проблем в 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;
}

Компилятор говорит:

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

Не могли бы вы помочь?

Ответы [ 8 ]

13 голосов
/ 22 января 2011

Вы используете две переменные с именами tree и node, но у вас также есть структуры typedef, помеченные как tree и node.

Измените имена переменных:

#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;
}
5 голосов
/ 22 января 2011

tree и node в вашем случае являются именами типов и не должны использоваться в качестве имен переменных позже.

tree *initTree() {
    tree *myTree = (tree*) malloc(sizeof(tree));
    node *myNode = (node*) malloc(sizeof(node));
    myTree->nodes[0] = myNode;
    return myTree;
}
3 голосов
/ 22 января 2011

Измените (tree*) и (node*) на (struct tree*) и (struct node*).Вы не можете просто сказать tree, потому что это тоже переменная.

2 голосов
/ 22 января 2011

Измените тело initTree следующим образом:

tree* myTree = (tree *)malloc(sizeof(tree));
node *myNode = (node *)malloc(sizeof(node));
myTree->nodes[0] = myNode;
return myTree;
1 голос
/ 22 января 2011

Не используйте typedef 'ed имена в качестве имен переменных, и нет необходимости приводить malloc(); в 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;
}
0 голосов
/ 22 января 2011

Интересно, что он компилируется чисто, если вы просто напишите распределение как:

tree *tree = malloc( sizeof *tree );

Часто считается, что лучше использовать "sizeof variable" а не "sizeof (тип)", и в этом случае стилистический Соглашение разрешает синтаксическую ошибку. Лично я считаю этот пример является хорошим примером, демонстрирующим, почему вообще плохая идея, так как код намного менее запутан, если написано:

struct tree *tree = malloc( sizeof *tree );
0 голосов
/ 22 января 2011

Помимо исходного вопроса, этот код, даже в его правильных формах, не будет работать, просто из-за того, что tree::nodes (извините за обозначение C ++) в качестве указателя на указатель не будет указывать на что-либо полезное правопосле того, как tree как было неправильно.Таким образом, tree->nodes[0], который в случае обычных указателей по сути такой же, как *(tree->nodes), не может быть разыменован.В любом случае, это очень странная голова для дерева, но вы должны по крайней мере выделить один node* для инициализации этого указателя на указатель:

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;
}
0 голосов
/ 22 января 2011

Я повторяю, что объяснение Мехрдада к сути.

Нередко в коде C вы определяете переменную с тем же именем, что и имя структуры, например, "node node;". Может быть, это не очень хороший стиль; это распространено, например, в ядро Linux, код.

Настоящая проблема в исходном коде заключается в том, что компилятор не знает, как интерпретировать «дерево» в «(tree *) malloc». Согласно ошибке компиляции, она, очевидно, интерпретируется как переменная.

...