Both functions are valid C++ and have well-defined behavior (modifying the data member of the A object created in main) in C++11 and later.
You are allowed to obtain a pointer to non-const from a pointer to const object type either directly with const_cast or indirectly with static_cast going through void* as you are doing in foo. That in itself is not a problem:
The cast to void* is possible because &a is a pointer to const A* which is not (top-level) cv-qualified. The cast from void* to A** is possible because void* can be cast to any object pointer type. Dereferencing the result is accessing the const A* object through a pointer to A*, but that is ok because the types are similar. (The last part seems to have been an aliasing rule violation prior to C++11, making this undefined behavior.)
However, modifying a const qualified object through a pointer to non-const obtained in such a way causes undefined behavior.
Since the object A a; that you are passing to the function is not const qualified, there is no problem.
But I think it is obvious why using such functions is dangerous. Changing the declaration A a; to const A a; will still compile because there is no type mismatch, but will have undefined behavior.
Both functions do exactly the same thing in all situations, as far as I can tell.