In C, I want to pass a pointer to another function so I coded the following,
node* list // contains linked list of nodes
void function (node* list){
/*Whatever I do here, I want to make sure that I modify the original list,
not the local copy. +
how do I pass the original pointer 'list' to this function so that I'm working
on the same variable? */
}
[EDIT]
I just like to clarify few things here,
I actually have a void function which takes a struct argument,
void function (struct value arg){ }
and in the struct, I'm defining one of my internal variables as,
node* list-> list;
so in my function, if I do something like,
arg->list
am I accessing the original list variable?
To answer your edit:
No, you are passing the structure by value, so the function contains a copy of the structure. If you don't return the structure in the function and grab it from where you called the function from, it will be lost.
Keep in mind that C does not pass by reference. It is instead simulated by passing the pointer. You could instead do this:
void function (struct value* arg)
{
....
}
And it will modify the original structure.
Related
I want the value of a pointer variable to be initialized to NULL at the start of the execution. This variable is used in a function and its value may also get changed within the function. But I do not want the value of this variable to reset to NULL whenever a function call is made. Instead, its value should be equal to the updated value from its previous function call. Cannot use global variables.
void function(struct node *variable) {
// changes value of pointer variable to something else
variable = something;
}
void another_function(void) {
// have to be initialised before passing in as argument or else will raise error
struct node *variable = NULL;
function(variable);
}
// then calling this function multiple times in main
another_function();
another_function();
help would be much appreciated.
Firstly, the pointer variable variable is local to another_function. It does not live outside of this scope.
Secondly, when you pass it to function, the variable parameter of that function is also local to that function. You immediately assign a value to that local variable, but that doesn't change the variable you passed in.
You can use the static keyword when declaring your initial pointer variable.
It will only be initialized when first encountered during the execution.
But as for now, your code will probably not do what you intend it to do.
The pointer variable in function is local and will have no effect on the value of variable in another_function.
You should use a pointer of pointer (also called a double-pointer or a nested pointer) for this effect.
Here is an example of how to use a double-pointer :
struct node {
int value;
};
void function(struct node** variable) {
if(*variable == NULL) {
*variable = (struct node*)malloc(sizeof(struct node));
(*variable)->value = 1;
}
printf("Value of variable is %d\n", (*variable)->value);
// Creating another struct node just for the demonstration
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->value = (*variable)->value + 1;
*variable = newnode;
}
void another_function() {
static struct node* variable = NULL;
function(&variable);
}
Basically, you pass the address of a pointer (located on the stack, which will always have a memory address) which let you modify the content of this pointer (a memory address on the heap) in the receiving function.
When you are dereferencing variable in function, what you get is not a value but another pointer.
Also parenthesis are important in this case.
Nested pointers can really be confusing, I hope that my explanation is somewhat clear.
To really understand how it works you need to understand what it's on the stack and what it's on the heap. But maybe this is an explanation for another time.
Of course, there is no memory management in this example and what I wrote contains memory leaks from all struct node that never are deallocated.
You should figure out how to do it depending on your program architecture.
?Hello,
I have implemented a struct of link, and with this made a list.
typedef struct link1 {
char* a;
char* b;
int i;
struct link1* next;
};
and I have functions for append, delete etc, from the list. Those functions get the first link in the list. The problem is the after using the functions the information didn't update.
Is there a way to pass the parameter of the first link, such that the list will be updated?
The first link is from type:
link1* first;
**I have tried to return the first link and it works, but I have nested function and I can't return those links in the external functions, so I think that the only way is to pass the paramter in other way.
Right now I send the parameter like this:
link1* first;
func(first);
void func(link1* l){...}
Thank you!
Link list manipulations, such as append, delete, etc., must often affect the "head" node in the list. For example, when the "head" node is deleted, then "head->next" must now assume the role as the new list head node. In such a case, your pointer
link1* first;
(which points to the head node of the list) must be modified to point to the "head->next" node. Unfortunately, passing first to a function in this manor
func(first);
does not allow func() to manipulate where 'first' is pointing. In order for func() to manipulate where 'first' is pointing, you must pass the "address" of first to func():
func(&first);
Now, if func() performs an operation such as 'delete node' or 'add node', it would have the address of 'first', and thereby it can change where 'first' is pointing:
func(struct link1 **first);
{
...
*first = head->next;
...
}
Whenever you'd like to change ANYTHING in a function using OUT BYREF parameter, u ought to send a pointer to the value that you are setting. I.E: If you were to set an int then u'd pass int *; If the value that you are assigning is of type struct link1* than you ought to pass a pointer to this type (pointer to pointer for the struct) where you can allocate the memory and set the pointer of the calling function.
void init(struct link1 **top)
{
//assign the pointer of the calling function
*top = ...;
}
calling function code
struct link1 *top;
init(&top);
Your problem is that you pass as an attribute in your function, the data of the first node and not the address of the data of your first node. How does this affects us in this case? Any changes you make on the first node, are just changes in a local variable of your function that lives in the stack of your program and when your function returns, this variable will be gone and so the changes you have made.
Check this out, you may understand it better. Imagine that this is a snapshot of your ram and the grey cells are memory indexes and the white cells are the corresponding data:
When you have a variable like b (lets call it a "single pointer" variable) and you pass b as an attribute to a function, you actually pass the data of b (0x1) and not the address of b (0x3). With this in mind, you can notice that you are able to change the contents of 0x1 (for example add 10 and make it '30') but you cannot change the contents of 0x3, which is what you want.
If you want to be able to change the root of your list from a function without returning something, you have to pass the address of the address, or the "double pointer" variable, like c. Passing it like this you are able to:
a) change the data of 0x3: *first = ....
b) change the data of 0x1: **first = ....
If you want to check if understood it, think want is going to happen if you change the data of first. For example:
int **temp = ....;
first = temp;
Now that we mention the theoretical part, in order to follow what i am proposing, you have to change your code into something like this:
func(&first); //pass the address of first variable
.
.
func(<variableType> **first) { // receive with double star
.
.
*first = ...; // change the root using single star
.
.
}
I have found this piece of code in a book:
void DeleteList(element *head)
{
element *next, *deleteMe;
deleteMe = head;
while (deleteMe) {
next = deleteMe->next;
free(deleteMe);
deleteMe = next;
}
}
Assuming that the argument that we are passing to the function is the pointer to the head of the list, why are we not passing a reference to that pointer?
If we don't do that, aren't we just going to delete a local copy of that pointer? That is why we pass reference pointers right? So the callee get the changes that have been done inside the function?
If we don't do that, aren't we just going to delete a local copy of that pointer?
Well, there is no such thing as a reference in C, but I assume you mean a pointer-to-pointer, and the answer would be no.
You are freeing the memory that the pointer points to on the heap, not the pointer itself. You are not mutating the pointer, so a copy is fine. Regardless of whether it is a copy or not, they point to the same place.
You are confusing this with assigning a completely new value to a variable passed to a function, in which case you would need to take a pointer-to-pointer. for example:
// only changes the local copy
void init(some_type *foo) {
foo = malloc(sizeof(some_type));
}
// initializes the value at *foo for the caller to see
void init(some_type **foo) {
*foo = malloc(sizeof(some_type));
}
Passing a pointer to a pointer (not a reference to a pointer, because C does not have references at all) would be a better solution, because you'd be able to null it out after the deletion. As it is currently defined, the function may leave dangling pointers behind if its caller is not careful. Other than that little problem, this solution is valid: the caller can always assign NULL to the list head manually after passing it to DeleteList().
Here is how I would rewrite this with a pointer to pointer:
void DeleteList(element **head) {
element *next, *deleteMe;
deleteMe = *head;
while (deleteMe) {
next = deleteMe->next;
free(deleteMe);
deleteMe = next;
}
*head = NULL;
}
The code from #dasblinkenlight can be made more compact.
void DeleteList(element **head) {
element *deleteMe;
while ((deleteMe = *head)) {
*head = deleteMe->next;
free(deleteMe);
}
}
When calling free, the pointer itself is not changed, so there is no need to pass it by reference.
You don't need to change the value of the head of the list in the caller.
// caller
DeleteList(head);
// head points to an invalid place (the place where the list used to be)
// for convenience sake, reset to NULL
head = NULL;
I want to create a generic stack. I want to implement it with a linked-list.
I created this structures stack_l :
typedef struct stack
{
void * data;
void (*copy)(void *o);
struct stack *next;
} stack_l;
I have some questions:
The second field of the structures is a pointer to a function, to copy a new data (passing by argument in a function Push).
The prototype of the function Push is:
stack_l * Push( stack_l * head, void * d );
Is it correct how I pass the pointer to the function copy?
I have to implement it in the function Push??
Is it necessary create a function NewStack (for example) to inizialize the field of the structures, or is better have only a Push function that create the 1st element if the stack is empty, and add new element on top if there is at least one element?
A void * need to be allocated with a malloc ?
First of all, you do not require different identifiers for stack and stack_l. Now, to your questions:
Your Push function is incompatible with the type of the copy field in stack_l. If you want to include a pointer to (member-)functions in your struct to make it look like C++, you still have to pass your object to these functions.
Yes ,you have to implement your functionality somewhere, and that cannot be within the definition of struct stack. This means that you do need some sort of constructor function (you may call it newStack if you like). Your constructor must at least initialise your function pointers (if you want to keep them). If you opt not to keep these function pointers you can put the initialisation code well in your push routine, as you suggested:
stack_l* stackPush(stack_l* head, void* content) {
// head might be NULL, meaning the stack is "empty" or it might be an actual pointer
// we don't care
stack_l* const front = malloc(sizeof(stack_l));
*front = (stack_l){.data = content, .next = head};
return front;
}
Note that you have to explicitly state what the empty stack is. So you may want to implement a constructor for clarity:
stack_l* stackCreateEmpty() {
retun NULL;
}
And maybe even a destructor:
void stackDestroyEmpty(stack_l* s) {
assert(s == NULL && "Tried to destroy non-empty stack.");
}
To your last question: As you see above, you have to use malloc to get space to hold your stack_l object, other than that, you do not need to allocate extra space for your void* member, as it is part of stack_l.
Hello I recently asked some questions on linked lists in C.
The link was found here
First I want to thank everyone for helping me with this. But I have one issue I cannot understand. I even asked the professor but he emailed me back with little information. Basically I am writing a linked list in C (see above link). One of the things the professor gives us in the header file is this:
void list_map( INTLIST *list, void (*f)(void *) );
/*Applies a function to each element of the list */
So I emailed him about this and said:
Another question, in the header file you did not define a sorting function, do we need to write a sorting function with the prototype and finally what is list_map
And he replied with:
You are asked to implement a sorting function f, which is called through list_map(list, f). Hope it clears your doubts.
My only doubts are this was not fully taught. I can understand how to sort the linked list in fact here is some pseudo code:
tmp=head;
while(tmp!=NULL)
{
tmp2=tmp->next; //pointer to next node
while(tmp2!=NULL)
{
if (tmp2->data < tmp->data)
{
int x = tmp2->data;
tmp2->data = tmp->data;
tmp2->data = x;
}
tmp2=tmp2->next;
}
tmp=tmp->next;
}
I know the experts might say this is not the most efficient, and I understand that right now I am just learning and trying to get things working. I can clean up afterwords...so on to my question.
My question is given I have the sort function (in the professor's case he calls it f). How would I call this sorting function when the signature is:
void list_map(INTLIST* list, void (*f) (void*));
Would I just say:
list_map(myList, f()); //apply function f to the current linked list
Or do I really need to define list_map somewhere? I am not the typical student just looking for someone to do my work. I am really trying to understand this as best I can.
Thanks to all of you.
[EDIT PORTION]
I wanted to add that one of the posters Kaleb P. said
"Thus, your job is to create a sorting
function that you will pass in to
list_map. Note that the correct syntax
for passing it in will be:"
So should my code simply be this:
in the .h file I prototype the function as:
void myCustomSort(void*);
And then in the .cpp it becomes:
void myCustomSort(void*f)
{
tmp=f->head;
while(tmp!=NULL)
{
tmp2=tmp->next; //pointer to next node
while(tmp2!=NULL)
{
if (tmp2->data < tmp->data)
{
int x = tmp2->data;
tmp2->data = tmp->data;
tmp2->data = x;
}
tmp2=tmp2->next;
}
tmp=tmp->next;
}
}
And to call it in main I would just do:
list_map(myListPointer, &myCustomSort);
But don't I need to define list_map anywhere? Because it is in the .h file do I not have to define it?
Assuming list_map is implemented like this, giving f each node in sequential order,
void list_map(INTLIST *list, void (*f)(void *)) {
INTLIST *node;
for (node = list; node; node = node->next)
f(node);
}
you can implement a selection sort
void list_sort(INTLIST *list) {
list_map(list, swap_head_with_smallest);
}
where void swap_head_with_smallest(void *) swaps the datum of a given node with the smallest of the data of any nodes following it in the list.
As this is homework, I'm trying not to give the whole solution away.
void swap_head_with_smallest(void *list) {
INTLIST *head = list;
INTLIST *smallest;
/* set smallest the smallest node of
head, head->tail, head->tail->tail, etc. */
/* swap head->datum and smallest->datum */
}
Your professor is trying to teach you a concept that's common in functional programming, which is the idea of a higher-order function. A higher-order function can take other functions as parameters, sort of like
list_of_cosines = map(cos, list_of_inputs)
where list of inputs is a series of floating point values, and cos is the normal cosine function. The map function will call cos for each value in list_of_inputs and return a list of the corresponding results.
C functions cannot take other function types as parameters, but they can take pointers to functions as parameters (usually termed a callback); the canonical example is the qsort() library function, which takes as one of its parameters a pointer to a function that accepts two pointers to void and returns -1, 0, or 1 depending on whether v1 < v2, v1 == v2, or v1 > v2, respectively. For example:
int compareIntValues(const void *v1, const void *v2)
{
int lv1 = *(int *) v1; // convert inputs from pointers to void
int lv2 = *(int *) v2; // to the type we're actually interested in
if (lv1 < lv2) return -1;
if (lv1 > lv2) return 1;
return 0;
}
int main(void)
{
int values[] = {3, 1, 4, 5, 7, 9, 6, 2};
...
qsort(values, // buffer containing items to sort
sizeof values / sizeof values[0], // number of items to sort
sizeof values[0], // size of each item
compareIntValues); // comparison function
...
}
qsort() will then call compareIntValues to order the elements in values. Similar to array expressions, a function designator will have its type implicitly converted from "function returning T" to "pointer to function returning T" depending on the context.
At this point I'm guessing, but it looks to me like your professor wants you to write the list_map function so that it will call a sorting function f with the list as the parameter, something like the following:
void list_map(INTLIST *list, void (*f)(void *))
{
// sort the list by passing it to f
f(list); // or (*f)(list);
}
void sortListAscending(void *ptr)
{
INTLIST *ilptr = ptr;
/**
* sort the list in ascending order
*/
}
void sortListDescending(void *ptr)
{
INTLIST *ilptr = ptr;
/**
* sort the list in descending order
*/
}
int main(void)
{
INTLIST *theList;
...
list_map(theList, sortListAscending); // sort the list in ascending order
...
list_map(theList, sortListDescending); // sort the list in descending order
...
}
The interface provided by your professor is a bit confused; either both the list pointer and the parameter to f() should be void * (in which case you could use list_map to map functions to different list types) or both the list pointer and parameter to f should be INTLIST * (since you seem to be dealing with INTLIST types).
If I'm right, then the exericise is a bit pointless on the surface (why not call the sorting function directly?), but it could be your professor is building up to something a bit more general-purpose. After all, there's no reason that f has to be a sorting function; it could be a function to display the list, or to save the list to a file, or something else.
I have a different example of how to use callbacks to sort a list here; it may help illustrate why this method is useful.
EDIT
ephemient's example of what list_map needs to do is probably much closer to what your professor intends than what I wrote.
The second parameter to list_map is a pointer to function returning void and taking in a void pointer. Since list_map appears to be a map function, I would guess that it will call f (the pointer to a function) for each element of the list.
Thus, your job is to create a sorting function that you will pass in to list_map. Note that the correct syntax for passing it in will be:
void yourCustomSort(void*);
list_map(myList, yourCustomSort);
I would guess that the void* being passed into your sorting function will probably be to a node within the linked list.
MergeSort is a good choice for sorting linked lists.
I believe that the list_map function calls the function pointer f() which is a pointer to a function that takes a void pointer and return void. If that is the case this is crazy way to implement a sort but doable.
Define a function like
void Test(void *)
{...}
And pass it in to the list_map() like so
list_map(listptr,Test);
I would assume your Test function gets called for each item in the list.
If in your node there is a pointer to the head of the list you have to use the pointer to the list as a frontier. Let me explain.
The map function is a common concept in functional programming, for now, you have just to know that is a function that get a list and apply another function (the applied function) to every node of the list was given to it. I bet you already knew it.
C language haven't, as far I remember, a map function, so you have to define one by your own it. It is not very difficult: Just start from the head of the list and walk to the tail. For every step pass the current listnode to the function that perform the operation you need to be performed (in this case the sort).
Now there is your assignment.
You cant get any data from the applied function (it returns void)
You have to walk down until the end of the list passing every single node to the function that do the sorting.
It is useless to sort the list you haven't already visited, as you would keep to sort it for every node (sorting an already sorted set it is not too smart to me) ;)
Your applied function get a single pointer. This in clearly stating that that pointer (the node you are at) represent a line: on his left (to the head) there is the part of list already sorted, to the right (to the tail) there are the wild elements.
Since Your applied function get as input just a simple void * , I think it is better to leave the pointers alone and exchange the payload of the nodes
Said that, the pseudocode for your sorting function, one of the possibile ones, can be:
void ascendingSort(void*f)
{
cursor=f->head;
placed=false;
while(!placed and cursor!=f) {
if (cursor->data < f->data) {
cursor = cursor->next;
} else {
swap( cursor->data, f->data);
placed=true;
}
}
while(cursor!=f) {
cursor = cursor->next;
swap(cursor->data, f->data);
}
}
Or, in a more concise form:
void ascendingSort(void*f)
{
cursor=f->head;
while(cursor!=f) {
if (cursor->data > f->data) {
swap( cursor->data, f->data);
}
cursor = cursor->next;
}
}