2010-05-05 11 views
18

Por lo que yo entiendo, GCC admite todas sus características C99 en C++. Pero, ¿cómo se maneja el aliasing estricto C99 en el código C++?C99 reglas estrictas de aliasing en C++ (GCC)

Sé que la conversión con C conversiones entre tipos no relacionados no es estricta-aliasing-safe y puede generar código incorrecto, pero ¿qué pasa con C++? Como el alias estricto no es parte del estándar de C++ (¿es correcto?), GCC debe especificar la semántica en sí misma.

Me figuran const_cast y static_cast emitidos entre tipos relacionados, por lo tanto son seguros, mientras que reinterpret_cast pueden romper reglas de alias estrictas.

¿Es esto una correcta comprensión?

Respuesta

31

No, probablemente estés mezclando cosas diferentes.

Las estrictas reglas de alias no tienen nada que ver específicamente con el estándar C99. Las reglas de alias estrictas están enraizadas en partes del estándar que estaban presentes en C y C++ desde el comienzo de tiempos [estandarizados]. La cláusula que prohíbe el acceso al objeto de un tipo a través de un lvalor de otro tipo está presente en C89/90 (6.3) y en C++ 98 (3.10/15). De eso se trata el alias estricto, ni más ni menos. Es solo que no todos los compiladores querían (u osaron) aplicarlo o confiar en él. Tanto los lenguajes C como C++ a veces se usan como lenguajes de "ensamblaje de alto nivel" y las reglas de alias estrictas a menudo interfieren con dichos usos. Fue GCC quien hizo esa movida audaz y decidió comenzar a depender de reglas de aliasing estrictas en optimizaciones, a menudo obteniendo quejas de esos tipos de "ensamblaje".

Es cierto que la forma más directa de romper las reglas de alias estrictas en C++ es reinterpret_cast (y el estilo C, por supuesto). Sin embargo, static_cast también se puede utilizar para tal fin, ya que le permite a uno para romper estricta aliasing mediante el uso de void * como un tipo intermedio en un "encadenada" Cast

int *pi; 
... 
double *pd = static_cast<double *>(static_cast<void *>(pi)); 

const_cast no puede romper estricta aliasing en un compilador compatible.

En cuanto a C99 ... Lo que C99 introdujo fue el calificador restrict. Esto está directamente relacionado con el aliasing, pero no es lo que se conoce como aliasing estricto per se.

+1

Tienes razón, estaba pensando en la palabra clave C.99 'restrict', en lugar de un alias estricto. Por alguna razón, ha arraigado en mi mente de esta manera ("C99" + "aliasing estricto"). –

+0

Entonces, ¿qué es exactamente la cláusula en cuestión?¿Significa que cualquier código C89/C99/C++ 98 que rompe reglas de alias estrictas es técnicamente incorrecto (salvo los modificadores específicos del compilador como -fno-strict-aliasing)? –

+0

@Checkers: agregué los números a mi respuesta. Y sí, el código que rompe reglas de alias estrictas muestra un comportamiento indefinido, también en C89 y en C++ 98. – AnT

4

static_cast también pueden romper las reglas de alias, porque el compilador está confiando en usted para asegurarse de que el tipo de destino esté relacionado con el tipo de tiempo de ejecución real del objeto. Considere:

extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap 
double d; 
void* pv = &d; 
int* pi = static_cast<int*>(pv); 
f(&d, pi); // assumption is violated 
2

El concepto es el mismo en Cpp; en eso puedes usar moldes de estilo C para guiarte a través de lo que se considera seguro con estricto aliasing.

En resumen: no, el enfoque para usar la fundición Cpp (que ha descrito) no cubrirá de forma segura todos los casos. Una forma común de romper las reglas es usar static_cast para lanzar punteros.

Simplemente encienda las advertencias del compilador - (o, debería) le dirá lo que no es seguro.

Cuestiones relacionadas