Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C passing a list as argument

Tags:

c

list

reference

So i have my definition of the list as a global variable:

typedef struct center {

  char center_name[100];

  char hostname[100];

  int port;

  struct center *next_center;

} center;

I need to add elements to the list. But these elements that i need to add are on a file, so:

 int main(int argc, char** argv) {
     center *head = NULL; 
     parse(argv, head);
  }

parse is a function, which read the file and add those read elements to a new center (all of this works, it double checked)

void parser (char** argv, center *head) {
   //read the elements i need to add
   //creates a newCenter and adds the elements read to the new center
   //this far it works
  addToCenter(newCenter, head); 
}

where:

addToCenter(center *newCenter, center *head){
   //adds newCenter to the list
   if (head == null)
      head = newCenter;
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }

}

Everything works, except that the list on Main always return as null. In other words, the reference is not being modified. I dont understand why, because i am passing a pointer to the list.

another solution i though is to create the head variable of the list as a global variable, but its better to avoid those situations.

Thanks in advance.

like image 335
Alessandroempire Avatar asked Jan 26 '13 13:01

Alessandroempire


2 Answers

Your list head is being passed by value. You need to pass the head pointer by address in case it is modified (which it will be).

Example:

addToCenter(center *newCenter, center *head) // <=== note: passed by value
{
   //adds newCenter to the list
   if (head == null)
      head = newCenter; // <=== note: modified local stack parameter only.
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }
}

should be:

addToCenter(center *newCenter, center **head) // <=== note: now passed by address
{
   //adds newCenter to the list
   if (*head == null)
      *head = newCenter;  // <=== note: now modifies the source pointer.
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }
}

Likewise with parse:

void parser (char** argv, center **head) // <=== again, the head-pointer's *address*
{
   //read the elements i need to add
   //creates a newCenter and adds the elements read to the new center
   //this far it works
  addToCenter(newCenter, head);  // <=== just forward it on.
}

And finally back in main:

int main(int argc, char** argv) 
{
     center *head = NULL; 
     parse(argv, &head);  // <=== note: passing address of the head-pointer. (thus a dbl-pointer).
}
like image 69
WhozCraig Avatar answered Sep 19 '22 00:09

WhozCraig


You need to pass it like this:

void parser (char** argv, center **head) {
   //read the elements i need to add
   //creates a newCenter and adds the elements read to the new center
   //this far it works
  addToCenter(newCenter, &head); 
}

addToCenter(center *newCenter, center **head){
   //adds newCenter to the list
   if (*head == null)
      *head = newCenter;
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }

}

And in main:

int main(int argc, char** argv) {
     center *head = NULL; 
     parse(argv, &head);
}

You have to do this because values in C are by default, passed by value. Since you're passing the address of the list by value, and not by reference. When you pass the variable head by reference as above program, you'll be able to modify the list and get the data back to the list. Otherwise, it is going to pass by value and the value of head will never be modified(hence you got NULL)

like image 44
Aniket Inge Avatar answered Sep 19 '22 00:09

Aniket Inge