p is just a regular pointer to an int pointing to a specific int object. You can make p point to any int object.
d does not point to any specific int object. Instead it points to a specific int member of cl for any cl object. It needs a cl object to be useful. You can use it to access the int member (val) of o by doing o.*d.