You free the memory pointed to by the pointer, not the pointer itself. There is no magic connection between a pointer and the memory it points to, so
is perfectly valid (but watch out because x is no longer pointing to valid memory).
If you want to free the pointer itself then you need to make the variable of type pointer to pointer to thing, not just pointer to thing:
free(*y); // frees the 20 bytes
free(y); // frees the pointer
You must not free the same memory twice
free(y); // OK, the 20 bytes are deallocated now
free(x); // likely to crash your program