Pointer is lost at function output

Asked

Viewed 113 times

3

I have the following function

typedef struct userDataStruct
{
    char name [MAX_NAME_LENGTH+1];
    struct userDataStruct *next;
} userDataType;

errorType GetUsers (userDataType **list)
{
    FILE *file;
    char buffer [LINE_LENGTH+1];
    userDataType *first, *previous, *new;

    file = fopen ("abc.dat", "r");
    first = previous = NULL;

    while (fgets (buffer, LINE_LENGTH+1, file))
    {
         new = (userDataType *) malloc (sizeof (userDataType));

         /* Resto do codigo */

        if (first == NULL)
            first = new;

        if (previous != NULL)
            previous->next = new;

        previous = new;
    }

    list = &first;

    return ok;
}

(ignore any syntax error, I had to dry up)

When I need to call this function, I declare a pointer and pass it with the null value. For example:

int main (void)
{
    userDataType **usersList = NULL,
            *currentUser;
    GetUsers(usersList);

    currentUser = *usersList; /* Aqui está o erro */
}

At the given line, the variable currentUser has the null value.

If I used the function malloc to allocate memory, this variable should not be pointing to the first element of the list?

Thank you in advance.

  • Do a [mcve], if you took out parts and it doesn’t work we may find that the problem is because of this.

  • The part I took just read the file, did not involve the problem in question.

  • There are other pieces missing, and exactly for missing and you saying no, we have no way of knowing if you have everything you need and then it becomes difficult to help properly.

  • I believe the problem is in the use of pointers, reading again I realized that I am changing the parameter of the first function (Getusers) and (I believe) this is not possible. But I don’t know how to do it properly.

  • The line where I do "parameter = &struct" does not have the expected effect.

1 answer

4


There are some problems with your code. In particular what is preventing a node from being assigned to its list is the way pointers (and values in general) are passed as parameters in C.

C adopts the "pass by value" convention. The simplified rule is: every function sees a local copy of the arguments that were passed in the call.

When you pass a pointer in the call the function sees a copy of the pointer, not the original pointer.

errorType GetUsers(userDataType **list)
{
    userDataType *first = // algo
    list = &first;
    return ok;
}

The instruction list = &first; can be read as "get the address" of first (which in turn is a pointer to a struct) and assign this value to list, which is a local copy of a pointer pointing to another null pointer. Local copy is completely independent of the original pointer and is discarded when the function goes out of scope.

What you really want to do within the body of function is:

*list = first;

The difference is subtle. This instruction can be read as:

  1. Get the value for which my local copy of list points (i.e., a pointer that initially points to NULL).
  2. Take the value of first (an address to a memory space you have allocated).
  3. Assign 2 to 1.

The point here is that you’re passing a copy of list as a parameter. No direct assignment to a local copy survives outside the scope of the function. You cannot directly change the original pointer. You can however change the value to which your copy points, which in turn modifies the original pointer.

Still on that front, knowing that your argument is only a copy of the address, I don’t think it makes sense to declare a pointer in the method main. You can declare a conventional pointer and pass its address as argument to the function, e.g.:

userDataType *usersList = NULL;
GetUsers(&usersList);
userDataType  *currentUser = usersList;.

This version avoids the explicit statement of a pointer pointer and makes clearer the intention of the call to GetUsers.

While these changes should solve your original problem, there are other issues with the code... Outside of exercises I would definitely rethink the API, this strategy using output parameter + return flag reminds me of coding patterns from the '90s. Calling your variable new also does not seem to be the best of ideas (C++ programmers pull their hair while reading this code).

  • 1

    Thank you very much! I thought you were actually changing the pointer copy. As for the API, it’s for a college job and, unfortunately, the professor says do it like this.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.