Suppose I have a function void myFun(int*) In C++ what exactly does the following mean
( void(*)(void*) )&myFun
Is it a pointer to a function that takes a (void*) as an argument and returns a void? Is this type of cast permitted?
As it stands, I'm pretty sure it's just not allowed.
If you remove the parens around the initial void to get:
void (*)(void *)
...then yes, it's a pointer to a function returning void and taking a pointer to void as its only argument. To cast to that type, you need to enclose the entire name of the type in parentheses, so you'd get: (void (*)(void *)), which you'd follow by the value being cast, to get:
(void (*)(void *))&myFun;
At least if memory serves, yes, this is allowed, though dereferencing the pointer (i.e., attempting to call the function it points at) via the result may give undefined behavior. In particular, when/if you call the function, it's expecting a pointer to int, and will (presumably) use whatever it points at as an int. If, however, what it points at isn't properly aligned to be used as an int, it's not likely to work as expected.
The cast is permitted, by 5.2.10 (6):
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling
a function through a pointer to a function type (8.3.5) 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.
This is equivalent to C 6.3.2.3 (8):
A pointer to a function of one type may be converted to a pointer to a function of another
type and back again; the result shall compare equal to the original pointer. If a converted
pointer is used to call a function whose type is not compatible with the pointed-to type,
the behavior is undefined.
In practice, calling through a function pointer with different but compatible argument types (especially pointer types) usually succeeds, and has the effect of a C-style cast on the arguments. This is by no means guaranteed, however; https://stackoverflow.com/a/189126/567292 discusses a case where gcc decided to make such undefined function pointer cast calls abort.
Related
From what I understand, casting function pointers to different types is allowed by the C++ standard (as long as one never invokes them):
int my_func(int v) { return v; }
int main() {
using from_type = int(int);
using to_type = void(void);
from_type *from = &my_func;
to_type *to = reinterpret_cast<to_type *>(from);
// ...
}
Moreover, there is no undefined behavior if I cast the pointer back to its original type and invoke it.
So far, so good. What about the following, then?
const bool eq = (to == reinterpret_cast<to_type *>(my_func));
Does the address hold, too, after the conversion, or is this not guaranteed by the standard?
While this is irrelevant to the question, a possible scenario is when one goes hard on type erasure. If the address holds, something can be done without having to know the original function type.
From [expr.reinterpret.cast].6 (emphasis mine):
A function pointer can be explicitly converted to a function pointer of a different type.
[...]
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, the standard explicitly allows casting function pointers to different FP types and then back. This is an exception to the general rule that reinterpret_casting function pointers is unspecified.
In my understanding, that means to == reinterpret_cast<to_type *>(my_func) need not necessarily be true.
https://en.cppreference.com/w/cpp/language/reinterpret_cast
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)
Why should I be interested in converting something to its own type? This reads to me as I would want to convert int to int.
Please correct me.
Because maybe you don't know if it is "its own type". Maybe you're in a template function, where you're calling some function whose return value you require to be reinterpret_castable to a template parameter T. So it's OK for that function to return a value of type T.
For a more useful example, let's say you're given some object of a type T. And you call a function on that that's supposed to return a pointer of some sort. And you want to cast this pointer to a char* and do some low-level messing around, perhaps to pass it to memcpy or something.
Well, what happens if the function returned a char*? That is, it returned a string. You need reinterpret_cast<char*> to still work.
I'm dealing with a special case where I can't use dynamic_cast directly because the object is a void*. Is using first static_cast on it and then dynamic_cast (on the result of the static_cast) bad practice? Is it wrong?
Here's an example of what I'm talking about:
MyClass* CastVoidPtr(void* pVoidPtr)
{
// casting it to MyClass so we could use dynamic_cast
MyClass* pTemp = static_cast<MyClass*>(pVoidPtr);
// returning the actual result that will make sure that we have a MyClass object or a nullptr
return dynamic_cast<MyClass*>(pTemp);
}
This would depend on how the pointer got to be a void* to begin with. If it was cast to the void* from the same type as be cast to (here MyClass*), then yes, this cast is fine and works as expected;
From cppreference on static_cast:
A prvalue of type pointer to void (possibly cv-qualified) can be converted to pointer to any type. If the value of the original pointer satisfies the alignment requirement of the target type, then the resulting pointer value is unchanged, otherwise it is unspecified. Conversion of any pointer to pointer to void and back to pointer to the original (or more cv-qualified) type preserves its original value.
Using static_cast in this way is essentially saying to the compiler "I know it is this type - trust me", and the compiler obliges.
The dynamic_cast can then be evaluated after this. It is typically used to cast to a more derived type. Here, you are casting to the same type - it is not doing anything particularly useful. If the type was a more derived type (e.g. MySpecialisedClass), then it would be fine.
As it stands, the function can be simplified to:
MyClass* CastVoidPtr(void* pVoidPtr)
{
return static_cast<MyClass*>(pVoidPtr);
}
Or to simply use a naked static_cast<>.
A side note; worth mentioning here for completeness is that reinterpret_cast has similar functionality;
Any pointer to object of type T1 can be converted to pointer to object of another type cv T2. This is exactly equivalent to static_cast<cv T2*>(static_cast<cv void*>(expression)) (which implies that if T2's alignment requirement is not stricter than T1's, the value of the pointer does not change and conversion of the resulting pointer back to its original type yields the original value). In any case, the resulting pointer may only be dereferenced safely if allowed by the type aliasing rules ...
I've got an iterator of Things. If I want to convert the current item to a pointer to the item, why does this work:
thing_pointer = &(*it);
But this not:
thing_pointer = reinterpret_cast<Thing*>(it);
This is the compiler error I'm trying to comprehend: http://msdn.microsoft.com/en-us/library/sy5tsf8z(v=vs.90).aspx
Just in case, the type of the iterator is std::_Vector_iterator<std::_Vector_val<Thing,std::allocator<Thing> > >
In
&(*it);
the * is overloaded to do what you logically mean: convert the iterator type to its pointed-to object. You can then safely take the address of this object.
Whereas in
reinterpret_cast<Thing*>(it);
you are telling the compiler to literally reinterpret the it object as a pointer. But it might not be a pointer at all -- it might be a 50-byte struct, for all you know! In that case, the first sizeof (Thing*) bytes of it will absolutely not happen to point at anything sensible.
Tip: reinterpret_cast<> is nearly always the wrong thing.
Obligitory Standard Quotes, emphasis mine:
5.2.19 Reinterpret cast
1/ [...] Conversions that can be performed explicitly using
reinterpret_cast are listed below. No other conversion can be
performed explicitly using reinterpret_cast.
4/ A pointer can be explicitly converted to any integral type large
enough to hold it. [...]
5/ A value of integral type or enumeration type can be explicitly
converted to a pointer. [...]
6/ A function pointer can be explicitly converted to a function
pointer of a different type. [...]
7/ An object pointer can be explicitly converted to an object pointer
of a different type. [...]
8/ Converting a function pointer to an object pointer type or vice
versa is conditionally-supported. [...]
9/ The null pointer value (4.10) is converted to the null pointer
value of the destination type. [...]
10/ [...] “pointer to member of X of type T1” can be explicitly
converted to [...] “pointer to member of Y of type T2” [...]
11/ A [...] T1 can be cast to the type “reference to T2” if an
expression of type “pointer to T1” can be explicitly converted to the
type “pointer to T2” using a reinterpret_cast. [...]
With the exception of the integral-to-pointer and value-to-reference conversions noted in 4/, 5/ and 11/ the only conversions that can be performed using reinterpret_cast are pointer-to-pointer conversions.
However in:
thing_pointer = reinterpret_cast<Thing*>(it);
it is not a pointer, but an object. It just so happens that this object was designed to emulate a pointer in many ways, but it's still not a pointer.
Because * operator of iterator is overloaded and it return a
reference to the object it points on.
You can force it by thing_pointer = *(reinterpret_cast<Thing**>(&it));. But it's undefined behavior.
Because iterator is not a pointer. It is a class of implementation-defined structure, and if you try to reinterpret it to a pointer, the raw data of the iterator class will be taken as a memory pointer, which may, but probably will not point to valid memory
The first gets a reference to the object, then takes the address of it, giving the pointer.
The second tries to cast the iterator to a pointer, which is likely to fail because most types can't be cast to pointers - only other pointers, integers, and class types with a conversion operator.
I can't think of any practical use of multiple asterisks in the function call:
void foo(int a, char b)
{
}
int main(void)
{
(**************foo)(45, 'c');
//or with pointer to function:
void (*ptr)(int, char) = foo;
(******ptr)(32, 'a');
}
Why is this thing allowed both in C and C++?
One of the standard conversions, in both C and C++, is the function-to-pointer conversion; when a function name appears in an expression, it can be converted into a pointer to that function. So:
foo is equivalent to &foo
*foo is equivalent to *(&foo), or foo
**foo is eqivalent to **(&foo), or *foo, or foo
and so on.
This means that you can legally add as many * as you like before a function name without changing its meaning. There's no reason to do that, though.
Why is this thing allowed both in C and C++?
I can't speak for C++, but for C at least a function designator is converted to a pointer:
6.3.2.1 - 4
A function designator is an expression that has function type. Except
when it is the operand of the sizeof operator or the unary & operator,
a function designator with type ‘‘function returning type’’ is
converted to an expression that has type ‘‘pointer to function
returning type’’.
Applying the indirection operator yields a function designator:
6.5.3.2 - 3
The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator
So no matter how many times you apply the indirection operator you'll get the same thing: a function designator that's immediately converted to a pointer.
In my opinion there's little or no use in doing this.
Because the * operator expects an address value. And whenever a value is expected (as opposed to an object or function glvalue), the lvalue to rvalue, function to pointer and array to pointer conversions are applied on an operand. So the dereferenced function immediately again converts to a pointer when again dereferenced.
These all either read values from objects or produce a pointer value that refers to the beginning of an array or function respectively.
These rows of dereferences have no purpose other than for the lulz of it.
The way i understand it is
* is a pointer to a memory address
& is the value at the Memory address
*foo means pointer to foo memory address
**foo means *(*foo) *(foo memory address) This is a different value from *foo
it continues like that...