Here is an example I have at hand that shows that when you are using an optimizing compiler, there is no such thing as “just pointers to addresses in memory”. There are plenty more examples, but I do not have the other ones at hand.
Please correct me if I am wrong, but I think here the optimization is possible because "* p = 2" is UB, because the compiler can assume that "p" points to invalid memory. For this assumption, the compiler must know that "realloc" invalidates its first argument.
How does it know that? The definition of "realloc" lives in the source of "libc.so", so the compiler should not be able to see into it. Its declaration in "malloc.h" does not have any special attributes. Does the standard and/or the compiler handles "realloc" differently from other functions?
edit:
It looks like clang inserts a "noalias" attribute to the declaration of "realloc" in the LLVM IR, so it seems it does handle "realloc" specially.
https://gcc.godbolt.org/z/Budx3n