"A pointer is a piece of memory/register that contains an address, and an address is just a bit pattern."
This is true on virtually every modern system, but (if memory serves) not literally every system ever, and the C standard leaves room for some surprising things in some places. It would have been very nice if the author had actually included some references, though.
The problem with assuming things like a pointer working like an integer, is that compiler vendors may choose to start taking advantage of any undefined behavior and point to the standard if you complain.
Nothing in this article is wrong. What adds to your knowledge of C is that certain operations on C pointers that would make sense if they were just bit pattern are actually undefined behavior. Undefined behavior may lead to subtle bugs due to how compilers do optimizations.
> I don't see how [. . .] is undefined behaviour.
This is a perfectly meaningless sentence. "Undefined behavior" doesn't mean "things which don't make sense in a particular implementation", it literally means behavior not defined by the spec. The spec declines to define the meaning of p==q when p and/or q is a freed pointer. There's nothing to "see" here: it's just not defined.
#include <stdio.h>
int main(void)
{
int x, y;
int *p = &x + 1;
int *q = &y;
printf("%p %p %d\n", p, q, p == q);
return 0;
}
prints 0x7f7fffffdafc 0x7f7fffffdafc 0