Passing Null Pointer in Function

10,007

Solution 1

I'm going to guess what you really mean with your question and try to give a decent answer.

I guess you want to change num_results to be equal to num by passing it to the function set as a pointer, and I can see a few mistakes you've made:

  1. You probably have this in your full code, but don't forget to #include <stdio.h> to use printf() and to #include <stdlib.h> to use malloc()
  2. Your function set() should be declared before main(), you can do this by declaring a prototype before main() or simply defining the set() function before main().

Now let's go to your solution: you want to pass the num_results as a parameter to a function, allocate some memory and assign the address to num_results and then update the value to the one in num.

When you pass an int * as a parameter, I guess you already know that by passing int you are simply giving a copy of what is inside an int variable. This works the same way with an int *, you are not passing a reference to num_results so that you can update the address of the pointer, you are passing a copy of the current address, NULL, which will not be modified. What could be modified is what is inside of the current address, but the current address is NULL, so not can really be modified.

Since you want to allocate memory and assign its address to num_results, you must pass a pointer to a pointer, so you are passing the address of where your int* variable is being kept and where you can actually change it.

This way, your function should look like void set(int ** results, int num) and you should call it with set(&num_results, num), so you are passing a reference to num_results, where you can change the address it points to, currently NULL and then the address returned by malloc().

You'd also have to change the body of your function, because you're now using an int **, you want to assign the new address to *results, because results == &num_results, and assign num to **results, because *results = num_results.

I hope my explanation is not very confusing and hopefully someone can explain it better with another answer or by editing mine. Final code:

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

void set(int ** results, int num){
    *results = malloc(sizeof(int));
    **results = num;
}

int main(void) {
    int * num_results = NULL;
    int num = 4;
    set(&num_results, num);
    printf("%d\n", *num_results);
    return 0;
}

Solution 2

set(num_results, num);

Here NULL is getting passed to results variable in set(), when you allocate memory to results, NULL is getting replaced by valid memory address, but you need to understand it will be held in results variable only as its a local variable to set()

You should either pass address of num_results to set() so that memory allocated in set() is retained in main(), or just allocate memory to num_results in main function then pass it to set() as done below:

#include <stdio.h>
int main() {
    int *num_results = NULL;
    int num = 4;
    num_results = malloc(sizeof(int));
    set(num_results, num);
    printf("%d\n", *num_results);
    return 0;
}

void set(int *results,int num){
    *results = num;
}

Another example would be:

#include <stdio.h>
#include <stdlib.h>
void set(int **r, int num);
int main() {
    int *num_results = NULL;
    int num = 4;
    /*num_results = malloc(sizeof(int));*/
    set(&num_results, num);
    printf("%d\n", *num_results);
    return 0;
}

void set(int **results,int num){
    *results = malloc(sizeof(int));
    *(*results) = num;
}

Solution 3

How do I adjust the content of the helper function to update num correctly?

That seems the wrong question, as your set() function seems intended to copy the value of num elsewhere, not to update num itself.

One of your problems is where to copy it. Presently, you allocate some memory for that dynamically, and copy it there. That's fine as far as it goes, but the pointer to the allocated memory is not conveyed back to the caller. This is because all C functions pass arguments by value, and in particular, your main() passes the first argument of set() by value (a value of type int *). Modifying the function's copy does not affect its caller's copy -- that's what pass-by-value is all about.

You may be overlooking a simple fact: dynamic allocation is not the only way to obtain a valid pointer value, nor even the the most important or common. When you see a pointer, you should not automatically go looking for malloc(). You can very easily get a pointer from an array, but perhaps even more importantly, you can get a pointer value by applying the address-of operator (&).

For your set() function to do work that its caller can see without resorting to global variables or changing its signature, the caller must pass as the first parameter a valid pointer to an object that the caller can access, such as one of its own local variables. The pointer is passed by value so the function gets a copy, but it's a copy: it points to the same object that the caller's pointer did. The set() function can therefore modify the pointed-to object via its copy of the pointer to it.

So suppose your main() declared its own local variable result, an int. What do you suppose it could do with &result?

Share:
10,007
Admin
Author by

Admin

Updated on June 27, 2022

Comments

  • Admin
    Admin almost 2 years

    This variable num remains at 0. I suspect this is because I am passing in a NULL pointer, but I am constrained to the main (and parameters) as is. How do I adjust the content of the helper function to update num correctly?

    int main(void) {
        int * num_results = NULL;
        int num = 4;
        set(num_results, num);
        printf(“%d\n”, *num_results);
        return 0;
    }
    
    void set(int * results,num){
        num_results = malloc(sizeof(int));
        *num_results = num;
    }