There is the code that I've written for experiments with reinterpret_cast<T>
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
int foo()
{
cout << "foo" << endl;
return 0;
}
void (*bar)();
int main()
{
bar = reinterpret_cast<void (*)()>(foo); //Convertion a function type to a pointer to function type
bar(); //displays foo. Is it UB?
}
First of all why such reinterpret_cast
convertion permitted? I thought such conversion is ill-formed.
reinterpret_cast in C++ | Type Casting operators. reinterpret_cast is a type of casting operator used in C++. It is used to convert one pointer of another pointer of any type, no matter either the class is related to each other or not. It does not check if the pointer type and data pointed by the pointer is same or not.
Assuming that alignment requirements are met, a reinterpret_cast does not change the value of a pointer outside of a few limited cases dealing with pointer-interconvertible objects:
If the implementation provides std::intptr_t and/or std::uintptr_t, then a cast from a pointer to an object type or cv void to these types is always well-defined. However, this is not guaranteed for a function pointer.
Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility . 1) An expression of integral, enumeration, pointer, or pointer-to-member type can be converted to its own type. The resulting value is the same as the value of expression. (since C++11)
The standard (C++11 §5.2.10/6) says
A pointer to a function can be explicitly converted to a pointer to a function of a different type. The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined. Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
So it is undefined behavior.
Formally calling via the pointer casted to different function type is Undefined Behavior (by C++11 §5.2.10/6).
In practice you're casting away a function result of type int
, that would be returned in a register. So about the worst that can happen when you call via the casted pointer, is that contrary to the compiler's expectations a register has changed value.
Another practical consideration: C++ does not support casting between function and data pointers, but Posix effectively requires cast to void*
and back to work OK. The C++ restriction is presumably in support of Harvard architecture machines, where instructions are not retrieved via the same bus and memory as ordinary data. But the Posix round-trip would presumably work also on such architecture, unless the data address space was much smaller than the instruction address space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With