The << operator is overloaded for char*, so that it treats the pointer as if it were a C-style string. So what you're seeing is the data in the memory pointed to by pp, interpreted as if it were an array of characters.
the address is what it is, regardless of how you type it, by the way.
pp = (char*)p; //pp has the same value as p. the difference is that when you index it, eg pp[1] vs p[1] you move a different number of bytes from the starting point (the value in p and pp is the starting point). A more interesting program then, would print the address of p[1] and pp[1] as integers (hex or not) .. they will not be the same.