¿Es un comportamiento indefinido 'reinterpretar cast' a 'T *' a ' T ( * ) [N]`?


Considere el siguiente escenario:

std::array<int, 8> a;
auto p = reinterpret_cast<int(*)[8]>(a.data());
(*p)[0] = 42;

¿Es este comportamiento indefinido? Creo que lo es.

  • a.data() devuelve un int*, que no es lo mismo que int(*)[8]

  • Las reglas de aliasing de tipo en cppreference parecen sugerir que reinterpret_cast no es válido

  • Como programador, sé que la ubicación de la memoria apuntada por a.data() es una matriz de 8 int objetos

¿Hay alguna regla que yo soy falta que hace que este reinterpret_cast válido?

Author: Vittorio Romeo, 2018-01-25

2 answers

Un objeto array y su primer elemento no son interconvertibles por puntero*, así que el resultado de la reinterpret_cast es un puntero de tipo "puntero a matriz de 8 int" cuyo valor es " puntero a a[0]"1.En otras palabras, a pesar del tipo, en realidad no apunta a ningún objeto de matriz.

El código luego aplica la conversión de matriz a puntero al lvalue que resultó de desreferenciar dicho puntero (como parte de la expresión de indexación(*p)[0])2. Esa conversión es el comportamiento solo se especifica cuando el lvalue realmente se refiere a un objeto array3. Dado que el lvalue en este caso no lo hace, el comportamiento es indefinido por omisión4.


*Si la pregunta es " ¿por qué un objeto array y su primer elemento no son pointer-interconvertibles?", ya se ha preguntado: Interconvertibilidad puntero vs tener la misma dirección.

1Véase [expr.reinterpretar.reparto] / 7 , [conv.ptr]/2, [expr.estática.cast] / 13 y [básico.compound] / 4 .

2Véase [básico.lval]/6, [expr.sub] y [expr.add] .

3[conv.array] : "El resultado es un puntero al primer elemento de el array."

4[defns.undefined] : undefined behavior es " comportamiento para el que este documento no impone requisitos", incluyendo "cuando este documento omite cualquier definición explícita de comportamiento".

 12
Author: T.C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-25 21:10:02

Sí, el comportamiento es indefinido.

int* (el tipo devuelto de a.data()) es un tipo diferente de int(*)[8], por lo que está rompiendo las estrictas reglas de aliasing.

Naturalmente, sin embargo (y esto es más para el beneficio de los futuros lectores),

int* p = a.data();

Es perfectamente válido, al igual que la expresión resultante p + n donde el tipo integral n está entre 0 y 8 inclusive.

 7
Author: Bathsheba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-25 14:44:40