dynamic_cast helps you check the validity while performing downcasting.  
It returns a NULL or throws an exception(std::bad_cast for References)if the pointer or the reference cannot be safely downcasted.
Would you use dynamic cast in a frequently run method? Does it have a large overhead?
dynamic_cast does use some additional RTTI(Run Time Type Information) for determining the validity of cast. So there is an overhead for sure. Typically, a pointer to typeinfo of the type will be added to the virtual table. I say typically, because virtual mechanism itself is compiler implementation dependant detail(may vary for different compilers). 
You will have to profile your code using some good profiling tools to determine if calling dynamic_cast repeatedly reduces the performance of your code.
What exactly IS the pointer returned by dynamic_cast. A pointer to the same address? a pointer to a different instance?
It is easier to understand when instead of analyzing downcasting with dynamic_cast we analyze upcasting. Given a type base and another type derived that inherits from base, the derived type will contain a subobject of type base. When a pointer to a derived object is upcasted to a pointer to base, the result of the operation will be the address of the base subobject inside derived. Performing a dynamic_cast reverts that operation, and returns a pointer to the derived object that contains a base subobject in the address passed as argument (static_cast does the same, but it will apply the possible offset without actually checking the runtime type).
In the simplest case, with single (non-virtual) inheritance the derived subobject will be aligned base, but in the event of multiple inheritance, that will not be the case:
struct base {
   int x;
   virtual void foo() {}
};
struct another_base {
   virtual void bar() {}
};
struct derived : base, another_base {};
int main() {
   derived d;
   base * b = &d;           // points to the base subobject inside derived
   another_base * o = &d;   // points to the another_base subobject inside derived
   std::cout << std::boolalpha
       << ( static_cast<void*>(b) == dynamic_cast<derived*>(b) ) << "\n"
       << ( static_cast<void*>(o) == dynamic_cast<derived*>(o) ) << std::endl;
}
The program will print true, false. Note that you have to explicitly cast one of the pointers to void* if you want to compare them, or else the compiler will perform an implicit upcast the downcasted pointer.