The reason you can't do bitwise pointer operations is because the standard says you can't. I suppose the reason why the standard says so is because bitwise pointer operations would almost universally result in undefined or (at best) implementation-defined behavior. So there would be nothing you could do that is both useful and portable, unlike simpler operations like addition.
But you can get around it with casting:
#include <stdint.h>
void *ptr1;
// Find page start
void *ptr2 = (void *) ((uintptr_t) ptr1 & ~(uintptr_t) 0xfff)
As for C++, just use reinterpret_cast
instead of the C-style casts.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…