Eren Bellisoy
Eren Bellisoy

Reputation: 13

How do I change a pointers value in a function in C

the code is:

     int main(int argc, const char* argv[] )
     {
        struct node * initialpointer=NULL;
        insert("asd", initialpointer, 1);
        if(initialpointer!=NULL)
            printf("isnotnull");
        if (initialpointer==NULL)
            printf("isnull");
     }
     insert(char* x,struct node * initialpointer, int numberofelements){
        struct node B;
        B.word = x;
        B.parent = NULL;
        B.leftchild = NULL;
        B.rightchild = NULL;
        printf("%d", 12);
        if ( initialpointer == NULL){
           initialpointer = &B;
           B.parent = NULL;
        }
     }

So in the end I want initialpointer to point where nde B is but in the main method it prints it is null. So how can I change the initialpointer in function insert permanently?

Upvotes: 0

Views: 712

Answers (5)

hmjd
hmjd

Reputation: 122001

Do not return a pointer to a local variable, this will result in a dangling pointer:

struct node B;
...
initialpointer = &B;

You need to pass a pointer to a pointer to a struct node to insert() and malloc() a new struct node inside insert():

insert(char* x,struct node ** initialpointer, int numberofelements)
{
    if (NULL == *initialpointer)
    {
        *initialpointer = malloc(sizeof(struct node));
        if (*initialpointer)
        {
            /* Note: you should probably make a copy of 'x',
               using 'strdup()' or similar, otherwise there
               is requiremenet that 'x' exist for the lifetime
               of '*initialpointer': which would be error prone. */
            (*initialpointer)->word       = x;
            (*initialpointer)->parent     = NULL;
            (*initialpointer)->leftchild  = NULL;
            (*initialpointer)->rightchild = NULL;
        }
    }
}

This retains the logic of the original insert() as a node should only be created and assigned to initialpointer if initialpointer is NULL.

And invoke it:

struct node * initialpointer=NULL;
insert("asd", &initialpointer, 1);

Remembering to free() it when no longer required:

free(initialpointer);

Upvotes: 4

vulkanino
vulkanino

Reputation: 9134

Edited per @Paul Mitchell's comment.

 int main(int argc, const char* argv[] )
 {
    struct node* initialpointer = insert("asd");
    if ( initialpointer == NULL )
       /* handle the error */

    /* remember to free() all the allocated nodes */
 }


 struct node* insert(char* x)
 {
    struct node* initialpointer = (struct node*)malloc(sizeof(struct node));
    if ( initialpointer == NULL)
        return NULL;  

    initialpointer.word = x;
    initialpointer.parent = NULL;
    initialpointer.leftchild = NULL;
    initialpointer.rightchild = NULL;
    return initialpointer;
 }

This will allocate a single node (I've removed the numberofelements parameter).

To allocate space for more than a node, you have to pass a pointer to a pointer. But if I understand your intent, you want a node to be part of a linked structure, maybe a tree, so you don't need to create a container for the nodes, since you can traverse the structure to access the nodes.

Upvotes: 0

bitmask
bitmask

Reputation: 34654

This is problematic for two reasons.

First of all, you are changing a local-scope variable, since initialpointer is a parameter of your function. That means, regardless of its type, what you write to the variable itself is only visible inside your insert function. If you were writing to *initialpointer that would be whole different story.

Now, what is even more problematic is that B is a local variable that is sitting on the stack inside your function. Once that function is left, the storage location of B will be invalid. Hence, if you return the pointer to B, accessing that object outside of insert will invoke undefined behaviour and will very likely not work (you have a slim chance that that particular location has not been altered, but that is pure luck).

What you probably want instead of

initialpointer = &B;

is this:

*initialpointer = B;

This will copy the B object to the storage location that is referenced by the pointer variable. Now it is okay for B to go out of scope, because you copied everything to the initialpointer variable that is sitting inside main.

Note that the initialpointer variable inside main is a completely different thing than the one in insert!


One last thing, giving variables names that start with uppercase letters is not valid in any naming scheme I came across so far.

Upvotes: 0

Mike DeSimone
Mike DeSimone

Reputation: 42825

There are a couple problems with your code.

First is the problem you're having. The pointer you're passing to insert is passed by copy; the function gets a copy and main doesn't see your change. The solution to this is to pass a pointer to the pointer. See the POSIX function strtol for a standard library example of how this looks.

The second problem is that you're returning a pointer to a local, automatic (i.e. stack-allocated) variable. Since the stack is released on function exit, this pointer points to invalid memory when it is back in main. So instead you need to allocate B from the heap.

So, fixing things up:

 int main(int argc, const char* argv[] )
 {
    struct node * initialpointer=NULL;
    insert("asd", &initialpointer, 1);
    if(initialpointer!=NULL)
        printf("isnotnull");
    if (initialpointer==NULL)
        printf("isnull");
 }
 insert(char* x,struct node ** initialpointer, int numberofelements){
    struct node *B;
    B = (struct node*)malloc(sizeof(struct node));
    B->word = x;
    B->parent = NULL;
    B->leftchild = NULL;
    B->rightchild = NULL;
    printf("%d", 12);
    if ( *initialpointer == NULL){
       *initialpointer = B;
       B->parent = NULL;
    }
 }

Upvotes: 0

glglgl
glglgl

Reputation: 91139

struct node * initialpointer=NULL;
insert("asd", &initialpointer, 1);
...
void insert(char* x,struct node ** initialpointer, int numberofelements){
...
if ( *initialpointer == NULL){
    *initialpointer = &B;

But keep in mind that this as well won't work with your current B as auto (local) variable.

You must malloc() B.

And you are missing an else branch in your if statement.

Upvotes: 0

Related Questions