简体   繁体   中英

Difference between modifying a function parameter and modifying a local variable

I saw a function that takes a list and a function pointer, and applies this function to each element of the list.

ft_list.h

#ifndef LIST_H
#define LIST_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

typedef struct  s_list
{
    struct s_list *next;
    void    *data;
}       t_list;
#endif

ft_list_foreach.c

void    ft_list_foreach(t_list *begin_list, void (*f) (void *))
{
    t_list  *curr;

    curr = begin_list;
    while (curr)
    {
        (*f)(curr->data);
        curr = curr->next;
    }
}

But why declare t_list *curr? And not just increment begin_list until the end of the linked list(NULL)?

Although in this case declaring a new variable which holds the pointer to the list makes no difference, I would say that this is a good practice to never mutate the function parameters, only when the function's nature requires to do so (ie when you have an inout parameter, like a buffer). This unwritten rule will save you from a lot of problems in future when dealing with more complex functions.

Consider just a simple case where you would need for some reason to also destroy and free the contents of this list after applying the f function. Of course, in this simple example you would easily spot the issue, but there are cases when this wouldn't be that obvious.

So, again, even though here it makes no difference, I strongly recommend to always write your functions using this pattern and this will avoid a lot of weird and unexpected issues.

A function can be designed to return a value, although there is technically no explicit need to so, when passing a pointer to an object as argument to modify it in the function.

The reason for this is when you have a critical operation inside of the function, and there is an error with this operation, you can return a specific value to the caller to symbolize that an error occurred inside of the function.

I guess the author later (half) optimized the code of the function here as his/her first intent maybe was to add such a security mechanism or even prepare the code to maybe later add this if the function becomes more critical features.

It is a technique that you return the passed pointer, when the operations in the function were successful and fe NULL at an error.

Also a common technique is to reassign the passed pointer with the returned pointer value, although this is risky since you lose the reference in the caller completely if an error occurred in the called function.

Since you increment the pointer in the function, it would be not very good to return the incremented pointer as one might want to reassign the passed pointer with the return value, like:

int *p = //anything ;
p = foo(p);

You need to either store the passed pointer value inside of another separate pointer variable, increment this "copy" pointer and return the passed parameter variable

OR

store the value of the passed pointer into another local pointer variable, increment the parameter pointer and return the "copy" pointer.

Therefore it can make sense to use curr instead of begin_list to increment and use begin_list as return value at success.

Otherwise NULL if an error occurred.

Note that you need to change the return type from void to t_list * then.


Also:

Difference between modifying a function parameter and modifying a local variable

A parameter is a local variable.

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