Original questions
The main (most significant) difference is whether the value in the calling function can be changed.
- In the first example, the called function gets a copy of the pointer in the calling code, and cannot modify the pointer in the calling code.
- In the second example, the called function gets a pointer to the pointer, and by assigning to
*vet
in the called function, you can modify the value in the called function.
Why in the second case if I pass
&vet
can I allocate memory infunction()
and free it inmain()
and in the first one not?
In the second case, the code in function()
can modify the actual pointer in main()
, so the value of vet
in main()
ends up with the allocated pointer value, which can therefore be freed. In the first case, the value in main()
is not modified by the called function, so the data can't be freed by main()
.
How and where to malloc or realloc? And free?
In the first case, you can use malloc()
or realloc()
in the function, but you should also free the allocated memory before return unless your code stores the value in a global variable (in which case you can delegate to some other code to handle the free()
, but it had better be very clear which code has the responsibility, and in any case using global variables is probably not a good idea). Or unless you change the function signature and return a pointer to the allocated data which should be freed by the calling code.
In the second case, you can allocate or reallocate memory in the called function and leave it allocated to be used by other functions and to be freed by the calling function.
And modify vet in the function?
In both functions, you can modify the local vet
variable as you see fit; this is true of any parameter to any function. What you can't necessarily do is modify values in the calling function; you have to have a pointer to value in the calling function to do that. In the first function, you can't change the value of vet
in main()
; in the second, you can. In both functions, you can change what vet
points at. (One minor problem is the conflation of the name vet
in the three contexts — the main()
and the two different functions. The name vet
in the two functions points at different types of things.)
Extension questions
But is it freed in
function()
like, for example, this?
#include <stdio.h>
#define NUM (10)
struct example
{
/* ... */
}
void dealloc (struct example *pointer)
{
free (pointer);
}
int main()
{
struct example *e;
e = malloc (NUM * sizeof(struct example));
if (e == NULL)
return -1;
struct example *e_copy = e;
dealloc (e_copy);
return 0;
}
This code is legitimate. You pass (a copy of) the value of the pointer to the dealloc()
function; it passes that pointer to free()
which releases the allocated memory. After dealloc()
returns, the pointer values in e
and e_copy
are the same as before, but they no longer point to allocated memory and any use of the value leads to undefined behaviour. A new value could be assigned to them; the old value cannot be dereferenced reliably.
And what is the difference from this?
#include <stdio.h>
#define NUM (10)
struct example
{
/* ... */
}
int main()
{
struct example *e;
e = malloc (NUM * sizeof(struct example));
if (e == NULL)
return -1;
struct example *e_copy = e;
free (e_copy);
return 0;
}
The difference between this example and the last is that you call free()
directly in main()
, rather than from a function dealloc()
.
What would make a difference is:
void dealloc(struct example **eptr)
{
free(*eptr);
*eptr = 0;
}
int main()
{
...
dealloc(&e_copy);
return 0;
}
In this case, after dealloc()
returns, e_copy
is a null pointer. You could pass it to free()
again because freeing the null pointer is a no-op. Freeing a non-null pointer twice is undefined behaviour — it generally leads to problems and should be avoided at all costs. Note that even now, e
contains the pointer that was originally returned by malloc()
; but any use of that pointer value leads to undefined behaviour again (but setting e = 0;
or e = NULL;
or e = e_copy;
is fine, and using e = malloc(sizeof(struct example));
or such like also works.