0

What happens here in terms of allocation ? is it faulty situation to use pointers like this?

void f(int p[])
{ 
  p = (int*)malloc(sizeof(int));
  *p = 0;
}

int main()
{
  int *q = 0;
  q = (int*)malloc(sizeof(int));
  *q = 1;
  f(q);
  return 0;
}
H.cohen
  • 517
  • 3
  • 9
paypaytr
  • 199
  • 1
  • 1
  • 12
  • 1
    Well you're missing some `#include` directives, you're having the wrong signature for [`main`](https://en.cppreference.com/w/c/language/main_function), and it's a memory leak in the `f` function. Other than that there's nothing wrong with the code as you show it. Perhaps that you cast the result of `malloc`, which you [shouldn't do](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858). – Some programmer dude Jan 05 '19 at 07:58
  • 2
    1. For every `malloc()`, there ought be a `free()`. Leaks can be troublesome. 2. Casting `void*` in C is rarely a good idea. Specifically, only to function-pointers as a matter necessity when allowed. 3. `sizeof(TYPE)` is far more error-prone than `sizeof *pointer`. 4. `p` in `f()` might start initialized to the value of `q`, but is otherwise independent. – Deduplicator Jan 05 '19 at 07:58

3 Answers3

2

The short answer is that p and q are independent variables. So first p will be assigned the same value as q and then p gets a new value due to the malloc. q is not changed by the function call. However, there is a memory leak due to p (and q) not being freed.

You can see this using a few prints.

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

void f(int p[]) 
{
    printf("--------------------\n");
    printf("p is now %p\n", (void*)p);
    printf("p points to the value %d\n", p[0]);
    p = (int*)malloc(sizeof(int)); 
    *p = 0; 
    printf("--------------------\n");
    printf("p is now %p\n", (void*)p);
    printf("p points to the value %d\n", p[0]);
    printf("--------------------\n");
}

int main(){
    int *q = 0;
    q = (int*)malloc(sizeof(int));
    *q = 1;
    printf("q is now %p\n", (void*)q);
    printf("q points to the value %d\n", q[0]);
    f(q);
    printf("q is now %p\n", (void*)q);
    printf("q points to the value %d\n", q[0]);
    return 0;
}

The output (with a few comments to explain):

q is now 0x1912010        // In main q is initialized
q points to the value 1   // In main the location q points to is initialized
--------------------
p is now 0x1912010        // In function p first has the same value as q
p points to the value 1   // so it also points to the same as q
--------------------
p is now 0x1913040        // In function p gets a new value due to malloc
p points to the value 0   // and the pointed to memory gets a new value
--------------------
q is now 0x1912010        // Back in main q is the same as before the function call
q points to the value 1   // and the pointed to memory is unchanged as well
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
0

What I guess your question is about, it's the assignment

p = malloc(...)

in the function f.

That's a fully valid assignment, and works like any other assignment.


Consider this code:

void f(int p)
{
    p = 0;
}

int main(void)
{
    int q;
    q = 1;
    f(q);
}

In the function f there's a reassignment of the variable p, just like in your shown code. It's really just the same as for your code. It doesn't matter if p is a plain int variable, or a pointer variable. You can still reassign it as much as you want.

The thing to note is that arguments in C are passed by value. That means the value of the argument is copied into the functions argument variable (p in your case and in my example). Modifying the copy (i.e. p) will of course not modify the original. All modifications that the function f does will be lost once it returns.

So in my example, if you print the value of q after the call f(q), then it would show that q is equal to 1.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

whenever you ask for allocation on heap using malloc for example- you have to free it, if you don't you get a memory leak- so for 2 mallocs here you must use 2 frees.

And you need to keep in mind that when you send q to the function you send it BY VALUE so if you check *q in main it will still stay 1.

if you want to change the value q is pointing to in the function you can send f(int **).

in your example a way to go if you want to change a where a pointer is pointing and to avoid memory leak is:

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

void f(int** p)
{
    free(*p); /*first free the initial main allocated memory on heap */
    *p = malloc(sizeof(int)); /*now the pointer is pointing to the new allocation */
    if(NULL == *p)
    {
       return;
    }
    **p = 0;
}

int main(){
    int *q = NULL;
    q = malloc(sizeof(int)); /*ask for memory allocation */
    if(NULL != q)
    {
       *q = 1;
       f(&q); 
       printf("%d\n", *q); /*now pointer is pointing to the allocationasked for by f */
       free(q); /*free the allocated place on heap */
     }
    return 0;
   }
H.cohen
  • 517
  • 3
  • 9
  • I guess `"you can send f(int **)"` is another way of saying you must pass the *address-of* the pointer to the function in order to assign the starting address for the newly allocated block as the value for the pointer passed to the function so that the change is visible back in the caller. – David C. Rankin Jan 05 '19 at 09:11
  • @DavidC.Rankin That is a very articulate way of explaining that, thank you for your note. – H.cohen Jan 05 '19 at 09:24
  • I knew what you meant, but the OP may have struggled a bit. Also, you may want to tidy up (remove) the cast from `malloc` - See: [Do I cast the result of malloc?](http://stackoverflow.com/q/605845/995714) (and it would be nice to show a validation that the return was not `NULL`). Other than that your code is fine. – David C. Rankin Jan 05 '19 at 09:28