C++ static_cast from float** to void**
Just ran into this:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
float *a = new float[10];
void **b;
b = static_cast<void**>(&a);
delete(a);
return 0;
}
macbook:开发者_如何学CC nils$ g++ -Wall -g -o static_cast static_cast.cpp
static_cast.cpp: In function ‘int main(int, char**)’:
static_cast.cpp:9: error: invalid static_cast from type ‘float**’ to type ‘void**’
macbook:C nils$ clang++ -Wall -g -o static_cast static_cast.cpp
static_cast.cpp:9:9: error: static_cast from 'float **' to 'void **' is not
allowed
b = static_cast<void**>(&a);
^~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
macbook:C nils$
Why is it not allowed? While b = (void**)(&a); works.
$5.2.9/2 -
"An expression e can be explicitly converted to a type T using a static_cast of the form static_cast(e) if the declaration “T t(e);” is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is a reference type (8.3.2), and an rvalue otherwise. The expression e is used as an lvalue if and only if the initialization uses it as an lvalue."
Let us take the case of Code snippet 1 as below
float *f;
void *p = f;
Here initialization of 'p' is well-formed. This is in accordance with $4.2
An rvalue of type “pointer to cv T,” where T is an object type, can be converted to an rvalue of type “pointer to cv void.”
Now let us take the code in OP
In our case, 'E' is 'float **'
and 'T' is 'void **'
So, whether static_cast will work for the attempted conversion if 'p' can be initialized as shown below
float **f;
void **p = f;
The initialization of 'p' is ill-formed as it is not a valid condition listed under $4.10
Now, coming to why b = (void**)(&a);
works?
This is the case where an explicit cast is used ($5.4
). In this case, this explicit cast is equivalent of reinterpret_cast
($5.4/5
). In this particular case, this conversion is allowed ($5.2.1/7
).
Does this help?
See Should I use static_cast or reinterpret_cast when casting a void* to whatever.
you should use reinterpret_cast.
I've used static cast to cast from a child class to the parent class, or where I knew the the type conversion was safe. If I needed runt time verification, then I'd use dynamic_cast.
When you write C-style to cast you basically are circumventing the C++ type checks so that is very "forgiving". However in order to conform to C++ (and to be on the safe side) you should use the C++ casts static_cast,dynamic_cast or reinterpret_cast.
reinterpret_cast is the closest you can get in C++ to a C-cast without actually doing C-cast.
You probably don't want a void**
, but rather void*
, for the reason mentioned by Joe Gauterin in this comment
精彩评论