简体   繁体   中英

Why does the value of a Pointer change after a print?

#include <stdio.h>

#include "sorted_tree.h"

int insert_value(int value, struct TreeNode *n){
    if(value<n->value){
        if(n->left_child==NULL){
            struct TreeNode t={0};
            struct TreeNode *tpointer=&t;
            tpointer->value=value;
            tpointer->left_child=NULL;
            tpointer->right_child=NULL;
            n->left_child=tpointer;
            printf("links eingefügt\n");
        }else{
            insert_value(value,n->left_child);
        }
        return 0;
    }else if(value>n->value){
        if(n->right_child==NULL){
            struct TreeNode t={0};
            struct TreeNode *tpointer=&t;
            tpointer->value=value;
            tpointer->left_child=NULL;
            tpointer->right_child=NULL;
            n->right_child=tpointer; 
            printf("rechts eingefügt\n");        
        }else{
            insert_value(value,n->right_child);
        }
        return 0;
    }else{
        return 1;
    }
}

void print_inorder(struct TreeNode *n){
    if(n == NULL){
        printf("r");
        return;
    }
    else{
        print_inorder(n->left_child);
        printf("%d ", n->value);
        print_inorder(n->right_child);
    }
}

int main(){
    struct TreeNode t={0};
    struct TreeNode *tpointer=&t;
    tpointer->value=5;
    tpointer->left_child=NULL;
    tpointer->right_child=NULL;
    insert_value(6,tpointer);
    printf("%d",tpointer->right_child->value);
    printf("%d",tpointer->right_child->value);
}

The first printf() in the main outputs "6" which is correct, but the second one outputs a hug random nummer as if the address has been changed. The 6 should be inserted into the right child node so I expected 66 as the output. Why those this happen and how can I fix it?

The approach when a first node of a tree is not allocated dynamically as in your program

struct TreeNode t={0};
struct TreeNode *tpointer=&t;
tpointer->value=5;
tpointer->left_child=NULL;
tpointer->right_child=NULL;

is not a good. In fact you can not create or use an empty tree.

All nodes in a tree should be allocated dynamically when it is required.

So the pointer n within the function insert_value in general can be equal to NULL for an empty tree. You need to check it. Otherwise statements like this

if(value<n->value){

can invoke undefined behavior.

Also within the function you are setting a pointer to a local object of the type struct TreeNode as for example

        struct TreeNode t={0};
        struct TreeNode *tpointer=&t;

After exiting the function the local object t will not be alive. So an invalid pointer will be added to the tree.

You need to allocate a new node dynamically.

Also the function in fact returns an arbitrary number 0 or 1 because the function does not return the final value of subsequent recursive calls of the function.

Also it would be logically more consistent to return 1 in case when a new node is added and 0 otherwise.

I would declare and define the function the following way

int insert_value( struct TreeNode **n, int value )
{
    if ( *n == NULL )
    {
        *n = malloc( sizeof( struct TreeNode ) );
        ( *n )->value = value;
        ( *n )->left_child  = NULL;
        ( *n )->right_child = NULL;

        return 1;
    }
    else if ( value < ( *n )->value )
    {
        return insert_value( &( *n )->left_child, value );
    }
    else if ( ( *n )->value < value )
    {
        return insert_value( &( *n )->right_child, value );
    }
    else
    {
        return 0;
    }
}

And if in main you have a pointer to the root node declared like

struct TreeNode *root = NULL;

then the function is called like

insert_value( &root, value );
 struct TreeNode t={0};
 struct TreeNode *tpointer=&t;
 tpointer->value=value;

Those blocks of code inside the if/else if of insert_value are not correct. This is because struct TreeNode t={0}; creates an automatic variable with lifetime only within the enclosing scope. In this case, the lifetime is only within the if/else if block. Keeping a reference to the variable and using it beyond that will result in Undefined Behaviour.

The solution is to create variables that have lifetimes beyond the function. The most common way to do that is to use dynamically allocated memory:

struct TreeNode *tpointer = malloc(sizeof(*tpointer));

Don't forget to free all dynamically allocated memory when it is no longer needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM