tipo static_cast operadores español dato conversion const_cast binario c++ arrays casting type-safety static-cast

operadores - static_cast c++ español



¿Es legal lanzar un puntero a la matriz de referencia usando static_cast en C++? (1)

Tengo un puntero T * pValues que me gustaría ver como T (&values)[N]

En esta respuesta SO https://stackoverflow.com/a/2634994/239916 , la forma propuesta de hacerlo es

T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));

La preocupación que tengo sobre esto es. En su ejemplo, pValues se inicializa de la siguiente manera

T theValues[N]; T * pValues = theValues;

Mi pregunta es si el constructo de pValues es legal si pValues proviene de cualquiera de los siguientes constructos:

1:

T theValues[N + M]; // M > 0 T * pValues = theValues;

2:

T * pValues = new T[N + M]; // M >= 0


Respuesta corta: tienes razón. El yeso es seguro solo si pValues es de tipo T[N] y los dos casos que mencionas (diferente tamaño, matriz dinámicamente asignada) muy probablemente conduzcan a un comportamiento indefinido .

Lo bueno de static_cast es que se static_cast algunas comprobaciones adicionales en tiempo de compilación, por lo que si parece que estás haciendo algo mal, el compilador se quejará (en comparación con el feo estilo C que te permite hacer casi cualquier cosa), por ejemplo:

struct A { int i; }; struct C { double d; }; int main() { A a; // C* c = (C*) &a; // possible to compile, but leads to undefined behavior C* c = static_cast<C*>(&a); }

le dará: invalid static_cast from type ''A*'' to type ''C*''

En este caso, se lanza a void* , que desde la vista de los controles que se pueden realizar en tiempo de compilación es legal para casi cualquier cosa, y viceversa: void* puede devolverse a casi cualquier cosa, lo que hace que el uso de static_cast completamente inútil en el primer lugar ya que estas verificaciones se vuelven inútiles.

Para el ejemplo anterior:

C* c = static_cast<C*>(static_cast<void*>(&a));

no es mejor que:

C* c = (C*) &a;

y lo más probable es que conduzca a un uso incorrecto de este puntero y comportamiento indefinido con él.

En otras palabras:

A arr[N]; A (&ref)[N] = *static_cast<A(*)[N]>(&arr);

es seguro y está bien. Pero una vez que comienzas a abusar de static_cast<void*> no hay garantías en absoluto sobre lo que sucederá realmente porque incluso cosas como:

C *pC = new C; A (&ref2)[N] = *static_cast<A(*)[N]>(static_cast<void*>(&pC));

se vuelve posible