The C standard is not the final say on things, your compiler and platform are. The standard is merely the minimum specifications that are ideally to be supported on all platforms, however you will still be unpleasantly surprised if you rely on it as such.
[1] Spaceship operator. Think "return value of memcmp" but generalized to any operand types.
(Edit: and for any pointers that you can compare for ordering, you may also calculate their offset from one another. However, like GP said, in practice you can do that for any pointers on common platforms.)
One is trying to learn how your current target architecture actually works. This is not production code. It's a "where in memory did the compiler decide to put that" question. You may get the results you expect or you may get someting totally bizzare. But since the purpose is discovering how the compiler works there is no wrong result.
Another is if you are writing your own memory manager. Here there are a lot of pointer comparisons to not the same allocated objects. But a memory manager is very OS and architecture specific so you will probably have to rewrite it when porting the code.
Having said all that, I wouldn't subtract the two void pointers like the example did. I would have converted them both to integers first and then subtract. Again, since this is for debugging and/or learning purposes then it's OK to bend the language rules a bit.
(The only in any case not-undefined way of calculating some sort of difference value between such is with the use of the optional uintptr_t, but I'd guess this isn't a sort of undefined behaviour which triggers unwanted compiler tricks, anyway.)
What about kernels (Linux, Windows — doesn't matter)... how do you compare physical address pointer with virtual address pointer?
Sure, they have values. But that might not mean much. Pointers can point to entirely different address spaces.
The C language standard defines (pretty imperfectly in the case of processors with multiple address spaces like the 8051 scratchpad RAM) something like a least common denominator you can rely on to "write portable C".
But that's not truth, nor is "portable C" the goal to all engineering efforts. Pointers are numbers. Scratchpad registers can't have pointers taken to them. Those are truths, even if inconvenient.