2012-06-07 22 views
8

EjemploInicialización de un int const con un punto flotante literal

int main() 
{ 
    const int i = 1.0; // Notice I am assigning a double to an int here 
    char a[i]; 
} 

Pregunta

Compilar el código anterior con g++ -O0 -Wall -pedantic -ansi -std=c++11 da ningún error (excepto para una variable sin usar). Sin embargo, si quito -std=c++11, me sale el siguiente aviso:

advertencia: ISO C++ prohíbe longitud variable de matriz

Según this SO question, creo que en C++ 03, el código no es válido . Sin embargo, ¿alguien puede explicar cómo ha cambiado la regla en C++ 11?

(Esta pregunta fue el resultado de a previous question I respondió.)

+0

¿Querías hacer 'i' a double, not an int? – David

+0

@Dave: No, eso fue a propósito. Ver el enlace a la pregunta anterior. –

+0

FWIW, clang ++ 3.0 no muestra la advertencia VLA. No tengo g ++ para probarlo, pero supongo que la advertencia no desaparece si cambia la asignación a 'const int i = 1;'. ¿Lo hace? – jweyrich

Respuesta

7

Una matriz con destino debe ser una expresión constante integral, ver 8.3.4 [dcl.array]/1 (misma formulación en C++ 03 y C++ 11):

Si la expresión constante (5.19) está presente, será una expresión de constante integral y su valor será mayor que cero.

En C++ 03 una expresión constante integral no se puede inicializar mediante un literal flotante a no ser fundido a tipo integral, ver la última frase del 5,19 [expr.const]/1:

Un La expresión de constante integral puede implicar solo literales (2.13), enumeradores, const variables o datos estáticos miembros de tipos integrales o de enumeración inicializados con expresiones constantes (8.5), parámetros de plantilla no tipo de tipos integrales o de enumeración y expresiones sizeof. Los literales flotantes (2.13.3) solo pueden aparecer si se convierten a tipos integrales o de enumeración.

Esto significa que en C++ 03 i no es una expresión de la constante integral, por lo que no se puede utilizar como una matriz unida.

GCC y Clang permiten matrices de longitud variable como una extensión a C++ 03, por lo que se compilan con un límite no constante, pero aparece una advertencia con -pedantic. Cambio de inicializador de la constante de echarlo a los de tipo integral hace i una expresión constante integral válida:

const int i = (int) 1.0; 

Con que cambiar la matriz ya no es de longitud variable y no hay ninguna advertencia incluso con -pedantic.

En C++ 11 5.19 [expr.const]/3 dice:

A literal expresión constante es un núcleo de expresión constante prvalue de tipo literal, pero no Tipo de puntero. Una expresión constante integral es una expresión constante literal del tipo de enumeración integral o no codificado.

El precedente (bastante largos) párrafos describen las reglas para expresiones constantes de núcleo, pero básicamente en C++ 11 el doble inicializador no impide i ser una expresión constante núcleo, incluso sin una conversión, por lo que es una expresión de constante integral y, por lo tanto, una matriz válida vinculada, por lo que no hay advertencia.

+1

GCC * no * advierte sobre la inicialización constante entera incorrecta. Advierte sobre el uso de la extensión del compilador VLA (que C++ 11 ya no usa, ya que en C++ 11 la matriz puede inicializarse mediante una constante). –

+0

@Konrad, sí, acaba de editarlo para aclarar lo que quise decir con "lo permite" –

Cuestiones relacionadas