Short answer: Yes
Longer answer:
You are not calling free "on the variable", but on the value stored in the variable.
To better understand what is going on, it may be better to think of memory as a big array of bytes, and visualizing a pointer as a numeric index into that array. And on most architectures you are likely to encounter, this is actually what is going on behind the scenes.
When you do
void * ptr1 = malloc(50);
malloc
is reserving a block of 50 bytes and returning a pointer to that block. That pointer is nothing more than a numeric index telling us where in memory the reserved block starts.
In theory we could (on some architectures) write
int ptr1 = (int)malloc(50);
The reasons we are not doing it, are:
sizeof(int)
may not be large enough to hold a pointer
void *
tells the compiler that the numeric value stored in ptr1
should be treated as a memory address.
If we continue looking at your code:
void * ptr2 = ptr1;
There is nothing magical happening here. The "numeric value" stored in ptr1
is copied into ptr2
, just as if ptr1
and ptr2
were normal integer variables.
ptr1 = malloc(25);
Here you overwrite the content of ptr1
with a new "numeric value", but the old value
still exist as a copy in ptr2
.
free(ptr2);
Here you call free
with the value stored in ptr2
. This is the value returned by malloc(50)
. free
does not care which variable is holding that value/address. It only cares that the value/address points to the first byte of a block of memory that was reserved with malloc
.
In theory, if you knew that malloc(50)
returned the value 0xb00b1e5 you could do
free((void *) 0xb00b1e5);
But you can't safely predict what malloc
is going to return, so don't do that.