Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I modify a pointer that has been passed into a function in C?

So, I have some code, kind of like the following, to add a struct to a list of structs:

void barPush(BarList * list,Bar * bar) {     // if there is no move to add, then we are done     if (bar == NULL) return;//EMPTY_LIST;      // allocate space for the new node     BarList * newNode = malloc(sizeof(BarList));      // assign the right values     newNode->val = bar;     newNode->nextBar = list;      // and set list to be equal to the new head of the list     list = newNode; // This line works, but list only changes inside of this function } 

These structures are defined as follows:

typedef struct Bar {     // this isn't too important } Bar;  #define EMPTY_LIST NULL  typedef struct BarList {     Bar * val;     struct  BarList * nextBar; } BarList; 

and then in another file I do something like the following:

BarList * l;  l = EMPTY_LIST; barPush(l,&b1); // b1 and b2 are just Bar's barPush(l,&b2); 

However, after this, l still points to EMPTY_LIST, not the modified version created inside of barPush. Do I have to pass list in as a pointer to a pointer if I want to modify it, or is there some other dark incantation required?

like image 665
Paul Wicks Avatar asked Apr 20 '09 04:04

Paul Wicks


People also ask

Can a pointer be changed within function?

Example: Passing Pointer to a Function in C Programming When we pass a pointer as an argument instead of a variable then the address of the variable is passed instead of the value. So any change made by the function using the pointer is permanently made at the address of passed variable.

Can you reassign a pointer in C?

Although it might appear that they represent similar concepts, one of the important differences is that you can reassign a pointer to point to a different address, but you cannot do this with a reference.


1 Answers

You need to pass in a pointer to a pointer if you want to do this.

void barPush(BarList ** list,Bar * bar) {     if (list == NULL) return; // need to pass in the pointer to your pointer to your list.      // if there is no move to add, then we are done     if (bar == NULL) return;      // allocate space for the new node     BarList * newNode = malloc(sizeof(BarList));      // assign the right values     newNode->val = bar;     newNode->nextBar = *list;      // and set the contents of the pointer to the pointer to the head of the list      // (ie: the pointer the the head of the list) to the new node.     *list = newNode;  } 

Then use it like this:

BarList * l;  l = EMPTY_LIST; barPush(&l,&b1); // b1 and b2 are just Bar's barPush(&l,&b2); 

Jonathan Leffler suggested returning the new head of the list in the comments:

BarList *barPush(BarList *list,Bar *bar) {     // if there is no move to add, then we are done - return unmodified list.     if (bar == NULL) return list;        // allocate space for the new node     BarList * newNode = malloc(sizeof(BarList));      // assign the right values     newNode->val = bar;     newNode->nextBar = list;      // return the new head of the list.     return newNode;  } 

Usage becomes:

BarList * l;  l = EMPTY_LIST; l = barPush(l,&b1); // b1 and b2 are just Bar's l = barPush(l,&b2); 
like image 90
geofftnz Avatar answered Sep 21 '22 06:09

geofftnz