指针和价值观

时间:2013-03-24 15:35:24

标签: c pointers

我编写了以下代码,它正确打印了根值,但没有写入ret值。这里可能会打印一个内存地址(1707388)。我相信ret现在可以修改,结果将在main中看到。任何帮助表示赞赏。

#include <stdlib.h>

struct node{
int value;
    int order;
    struct node *left;
    struct node *right;
};

typedef struct node node_t;

node_t array[10];

void createTree(node_t *p, int order){
    p->value = rand()%10;
    p->order = order;
    printf("%i", p->value);
    printf(" ");
    printf("%i\n", p->order);
    if (!order){
        p->left = NULL;
        p->right = NULL;
        return; 
    }
    order--;
    createTree(&p->left, order);
    createTree(&p->right, order);
}

void traverse(node_t *current, node_t *ret, int size){
    printf("%i\n", current->value); 
    if (current->value > size){
        ret = current;
        traverse(&current->left, &ret, size);
        traverse(&current->right, &ret, size); 
    } 
    return;
}

int main(void){
    node_t *root = &array[0];
    node_t *ret;
    srand(time(NULL));
    createTree(root, 4);
    int i = 3;
    printf("%s", "root-value: ");
    printf("%i\n", root->value);
    traverse(root, ret, i);
    printf("%s", "root-value: ");
    printf("%i\n", root->value);
    printf("%i\n", ret->value);
    return 1;
}

4 个答案:

答案 0 :(得分:4)

此:

void createTree(node_t *p, int order)

应该是

void createTree(node_t **p, int order)

否则,您正在修改本地 node_t指针,而不是函数外部的指针。您的树也没有正确构建。

答案 1 :(得分:3)

您将ret按值传递给

void traverse(node_t *current, node_t *ret, int size){

当函数更改ret时,更改不会传播回调用者。

这意味着ret中的main()仍然未初始化,并且代码的行为未定义。

要解决此问题,请traverse返回ret,或将其作为node_t**

答案 2 :(得分:2)

代码存在一些问题。

首先,您没有为节点正确分配内存。在你的代码中,你传递错误的指针类型,而且指向未初始化区域。

在这里,如何以不同的方式使用它:

 node_t *createTree(int order)
 {
     node_t *result = malloc(sizeof(*result));
     result->value = rand() % 10;
     result->order = order;
     if (order)
     {
         result->left = createTree(order - 1);
         result->right = createTree(order - 1);
     }
     else
     {
         result->left = result->right = 0;
     }
     return result;
 }

然后,你的遍历函数需要一些块来限制再次失败的搜索:

node_t *traverse(node_t *current, int size)
{
    node_t *ret = NULL;

    if (current->value > size)
    {
        // assuming current node fit - stops the search
        ret = current;
    } 

    if (!ret && current->left)
    {
        // try left node
        ret = traverse(current->left, size);
    }
    if (!ret && current->right)
    {
        // try right node
        ret = traverse(current->right, size); 
    }
    return ret;
}

如果您需要(通常是),这里是destroyTree

void destroyTree(node_t *node)
{
    if (!node) return; // we treat NULL as a valid pointer for simplicity

    destroyTree(node->left);
    destroyTree(node->right);
    free(node);
}

这是一个用法示例:

node_t *root, *found;

root = createTree(4);
found = traverse(root, 3);
if (found)
{
   printf("Found!");
}
destroyTree(root);

答案 3 :(得分:1)

traverse(node_t *current, node_t *ret, int size)中,ret是一个堆栈变量。换句话说,您将指针按值传递,而不是通过引用传递

目前你做了什么与基本相同:

int f(int i) {
   ...
   i = <any value>;
   ...
}

在这种情况下,您只修改值的副本。

在您的程序中,您还要修改指针的副本。在函数外部,指针不会被修改。

如果要修改它,则需要传递指针:

void traverse(node_t *current, node_t **ret, int size){
    ...
    *ret = current;
    ...
    return;
}

createTree()也一样。