Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reinterpret_cast to function pointer

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.

like image 280
St.Antario Avatar asked Aug 05 '14 04:08

St.Antario


People also ask

How do you use reinterpret cast in C++?

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.

Does a reinterpret_cast change the value of a pointer?

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:

Can you cast from a pointer to an object type?

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.

What types of conversions can be done with reinterpret_cast?

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)


2 Answers

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.

like image 108
ahruss Avatar answered Sep 22 '22 17:09

ahruss


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.

like image 23
Cheers and hth. - Alf Avatar answered Sep 25 '22 17:09

Cheers and hth. - Alf