结构声明的一般功能

时间:2015-01-29 18:52:15

标签: c

我已经构建了一个通用的二进制搜索树。

typedef struct Tree {
    void* data;
    struct Tree *left;
    struct Tree *right;
}Tree;

使用不同数据类型变量创建树的两个函数。

Tree* GetNewTreeInt(){
    Tree* newTree = (Tree*)malloc(sizeof(Tree));
    *((int*)newTree->data);
    newTree->left = newTree->right = NULL;
    return newTree;
}

Tree* GetNewTreeChar(){
    Tree* newTree = (Tree*)malloc(sizeof(Tree));
    *((char*)newTree->data);
    newTree->left = newTree->right = NULL;
    return newTree;
} 

我试图创建一个通过地址存储函数的通用函数

Tree* CreateTree();

    int main() {
    void* root;
    scanf("%d", &choose);
    if(choose==0){
        Tree* CreateTree=GetNewTreeInt();
        (Tree*)root=CreateTree();
    }

但是我一直收到以下错误:调用对象类型“Tree *”(又名'struct Tree *')不是函数或函数指针

2 个答案:

答案 0 :(得分:2)

此:

Tree* CreateTree();

..声明一个函数CreateTree,它返回一个Tree*,没有完全定义函数(没有函数体,只是一个原型)。鉴于此:

Tree* CreateTree=GetNewTreeInt();

声明名为Tree*的{​​{1}}类型的变量,并调用CreateTree函数将其返回值赋给GetNewTreeInt()。由于您已经声明了具有相同名称的函数,因此这会给您带来错误。

如果您希望CreateTree成为函数指针,并将其指向CreateTree函数,则需要将其声明为(全局或GetNewTreeInt内,而不是两者) :

main

..然后将其指向Tree *(*CreateTree)(); ,如下所示:

GetNewTreeInt

..然后您可以通过指针调用函数,只需CreateTree = GetNewTreeInt; 和普通函数一样,例如:

CreateTree()

如果需要函数指针类型的typedef,可以按如下方式执行:

root = CreateTree();

...并将typedef Tree *(*CreateTreeFuncType)(); 声明为:

CreateTree

而不是使用前面提到的函数指针语法。

答案 1 :(得分:1)

看起来你正在尝试使用函数指针。要做到这一点,你需要声明一个函数指针,该函数指向一个函数,该函数直接返回Tree*而不是Tree*

if(choose==0) {
    Tree* (*CreateTree)(void);
    CreateTree = &GetNewTreeInt;
}

但是,您的两个函数是相同的,因为行*((int*)newTree->data);没有副作用。您可以创建一个这样的函数:

Tree* GetNewTreeInt(void){
    Tree* newTree = (Tree*)malloc(sizeof(Tree));
    newTree->left = newTree->right = NULL;
    return newTree;
}

当您访问tree->data时需要将void *强制转换为您知道其包含的类型的指针。如果您不知道外部具有哪种类型的树,则应该在结构中添加另一个字段,表示存储的数据类型。如果您只存储intchar等小数据类型,我建议使用union而不是void指针,因为union会将数据存储在内存中。无论哪种方式,您仍然需要树中的某些内容来指示其存储的数据类型。

typedef struct Tree {

    // 0 means there is an int in tree->data.i,
    // 1 means there is a char in tree->data.c
    int type; 

    union {
        int i;
        char c;
    } data;

    struct Tree *left;
    struct Tree *right;

} Tree;

然后你的两个功能变为:

Tree* GetNewTreeInt(void){
    Tree* newTree = (Tree*)malloc(sizeof(Tree));
    newTree->type = 0;
    newTree->data.i = 0; // Set an initial value
    newTree->left = newTree->right = NULL;
    return newTree;
}

Tree* GetNewTreeChar(void){
    Tree* newTree = (Tree*)malloc(sizeof(Tree));
    newTree->type = 1;
    newTree->data.c = '\0'; // Set an initial value
    newTree->left = newTree->right = NULL;
    return newTree;
}

你可以像这样使用函数指针:

if(choose==0) {
    Tree* (*CreateTree)(void);
    CreateTree = &GetNewTreeInt;

    Tree* tree = CreateTree();
    tree->data.i = 7;
}

每棵树都有一个data.idata.c,但不是两者都有,稍后当您浏览树木时,您可以检查其类型以找出哪个:

if ( tree->type == 0 ) {
    int data = tree->data.i;
} else if ( tree->type == 1 ) {
    char data = tree->data.c;
} 

修改

如果您真的想使用void *,您仍然可以将int type添加到您的结构中,并且在遍历时您可以执行以下操作:

if ( tree->type == 0 ) {
    int data = *(int *)tree->data;
} else if ( tree->type == 1 ) {
    char data = *(char *)tree->data;
}