theres a really wonderful way to describe in place quicksort
in particular:
let i,j be your initial upper and lower indices for an array a (or slice thereof) . randomly pick an integer $\ell$ in the interval [i,j] as the pivot $p=a[\ell]$. As for the the number of entries greater or equal to p, call this $m$.
We know that there are at most $\min(j-i -m+1, m)$ swap operations needed between the interval $[i, j-m]$ and the interval $[j-m+1,j]$ for us to be able to then recursively sort these two intervals. these swaps can be done by starting from indices $i$ and $j$ and scanning inward on both sides until each side has found an index that violates the ordering relative to the pivot value, at which point a swap is done, then the search continues inward, terminating at the point when these two searches meet.
edit: note that there is actually no special treatment needed for the pivot value, we just apply the swapping operation uniformly.
then recursively sort the intervals you get from the final placement of the pivot value.
this gives you the "c-style" in place quick sort, but explained in a a high level way that has very very clear correctness properties!
:)
note that this isn't a stable sort algorithm