Well ... no, not quite.
It's a valid pointer you get, but it's zero bytes long and cannot be dereferenced:
If the size of the space requested is zero, the behavior is implementation defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
It's a bit useless, as
is defined to accept a NULL value:
The free() function shall cause the space pointed to by ptr to be deallocated; that is, made available for further allocation. If ptr is a null pointer, no action shall occur. Otherwise, if the argument does not match a pointer earlier returned by a function in POSIX.1-2017 that allocates memory as if by malloc(), or if the space has been deallocated by a call to free() or realloc(), the behavior is undefined.
It's a lot clearer to just use
int *p = NULL;