2010-07-26 7 views
20

o "Declarar múltiples variables en una de ist bucle verboten"En C++ Por qué no puedo escribir un bucle for() así: for (int i = 1, doble i2 = 0;

?! mi código original era

for(int i = 1, int i2 = 1; 
     i2 < mid; 
     i++, i2 = i * i) { 

quería colocar a través de los primeros tan muchas plazas, y quería tanto el número y su cuadrado, y la parada de la condición depende de la plaza. Este código parece ser la expresión más limpio de intento, pero no es válido. Puedo pensar en una docena de formas de evitar esto, así que no estoy buscando la mejor alternativa, sino una comprensión más profunda de por qué esto no es válido. Un poco de abogacía lingüística, si se quiere.

Soy lo suficientemente viejo para recordar cuando había que declarar todas las variables al comienzo de la función, así que aprecio la sintaxis

for(int i = 0; .... 

. Al leer todo, parece que solo se puede tener una declaración de tipo en la primera sección de una declaración for(). Lo que puede hacer

for(int i=0, j=0; ... 

o incluso ligeramente el barroco

for(int i=0, *j=&i; ... 

pero no la a-me-sensata

for(int i=0, double x=0.0; ... 

¿Alguien sabe por qué? ¿Es esto una limitación de for()? O una restricción en las listas por comas, como "el primer elemento de una lista separada puede declarar un tipo, pero no a los otros? ¿Son los siguientes usos de comas elementos sintácticos distintos de C++?

(A)

for(int i=0, j=0; ... 

(B)

int i = 0, j = 0; 

(C)

int z; 
z = 1, 3, 4; 

Cualquier gurús por ahí?

============================================== ======

sobre la base de las buenas respuestas que he recibido, creo que puedo afilar la pregunta: ¿

en una sentencia for

for(X; Y; Z;) {..... } 

cuáles son X, y y Z ?

Mi pregunta era sobre C++, pero no tengo una gran referencia de C++. En mi referencia C (Harbison y Steele cuarta ed, 1995), que son los tres expresiones, y mi gcc requiere modo C99 a utilizar para (int i = 0;

En Stroustrup, sec 6.3, el de sintaxis de la sentencia se da como

para (para-init-afirmación; condición; expresión) declaraciones

Así C++ tiene una declaración sintáctica especial dedicado a la primera cláusula en para(), y podemos supongamos que tienen reglas especiales más allá de las de una expresión. ¿Suena esto válido?

+0

posible duplicado de [Problema de contador múltiple en For Loop] (http://stackoverflow.com/questions/2340073/multiple-counter-problem-in-for-loop) –

+0

posible duplicado de [¿Puedo declarar variables de diferente tipos en la inicialización de un bucle for?] (http://stackoverflow.com/questions/8644707/can-i-declare-variables-of-different-types-in-the-initialization-of-a-for-loop) –

Respuesta

16

int i = 1, double i2 = 0; no es una declaración de declaración válida, por lo que no se puede utilizar dentro de la instrucción for. Si la declaración no puede ser independiente fuera del for, entonces no se puede usar dentro de la instrucción for.

Editar: En relación con sus preguntas sobre los operadores de coma, las opciones 'A' y 'B' son idénticas y ambas son válidas. La opción 'C' también es válida, pero probablemente no hará lo que cabría esperar. z se le asignará 1, y las declaraciones 3 y 4 en realidad no hacen nada (es probable que su compilador le advierta sobre "declaraciones sin efecto" y las optimice).

Actualización: Para hacer frente a las preguntas en su edición, aquí es cómo el C++ spec (Sec 6.5) define for:

for (for-init-statement condition(opt) ; expression(opt)) statement 

It define además como sea for-init-statementexpression-statement o simple-declaration. Ambos condition y expression son opcionales.

El for-init-statement puede ser cualquier cosa que es un válido expression-statement (como i = 0;) o simple-declaration (como int i = 0;). La declaración int i = 1, double i2 = 0; no es válida simple-declaration de acuerdo con la especificación, por lo que no es válida para usar con for. Para referencia, un simple-declaration se define (en la Sección 7) como:

attribute-specifier(opt) decl-specifier-seq(opt) init-declarator-list(opt) ; 

donde decl-specifier-seq sería el tipo de datos además de palabras clave como static o extern y init-declarator-list sería una lista separada por comas de declaradores y sus inicializadores opcionales. Intentar poner más de un tipo de datos en el mismo simple-declaration coloca esencialmente un decl-specifier-seq donde el compilador espera un init-declarator-list. Al ver este elemento fuera de lugar, el compilador trata la línea como mal formada.

La especificación también señala que el bucle for es equivalente a:

{ 
    for-init-statement 
    while (condition) { 
     statement 
     expression ; 
    } 
} 

donde condition por defecto es "verdadero" si se omite.Pensar en esta forma "expandida" puede ser útil para determinar si una sintaxis dada se puede usar con un ciclo for.

+4

Adición: No es una declaración de coma válida PORQUE los tipos en una declaración de coma deben ser (por C la definición de idioma) el mismo. La misma razón por la cual la instrucción de coma 'int a = 0, int b = 0;' es equivalente a 'int a = 0, b = 5;' - los tipos de todas las variables declaradas después de la mayoría de la izquierda se heredan de la izquierda si ausente (o debe ser el mismo si está presente). –

+4

No existe una "declaración de coma". El operador de coma se usa para hacer "expresiones de coma" y las expresiones (de todos los tipos) son partes de enunciados. Pero esta no es una expresión, y esa coma no es un operador de coma. –

+0

Excelente respuesta, gracias. Dos puntos: 1) Mi compilador (g ++/Cygwin) no acepta int a = 0, int b = 0; 2) Pensé con aire de suficiencia "oh sí, yo * sé * lo que hace (C)", pero pensé que haría lo mismo que Perl. Perl evaluaría todos los elementos separados por comas y asignaría el último a z. ¡No es el mísmo! – Jonathan

1

Siempre que pueda escribir una declaración válida con el operador de coma ,, es aceptable.

+0

Eso no es del todo exacto, dado el contexto de la pregunta. –

1

C++ (también C y Java) no permiten la declaración de más de un tipo de variables en el alcance de un ciclo for. En la gramática, eso se debe a que la coma no inicia una nueva declaración en ese contexto. Efectivamente, solo se permite una declaración dentro de la declaración for(;;). La razón es que ese requerimiento es bastante inusual, y puedes obtenerlo solo con una construcción un poco más detallada.

13

En realidad es una limitación de sentencias de declaración:

int i=0, j=0, *k=&i;  // legal 
int i=0, double x=0.0; // illegel 

Así que, básicamente, la respuesta a su pregunta final es: (A) & (B) son los mismos. (C) es diferente.

Como BTA señala:

z = 1,3,4; 

es la misma que

z = 1; 

Sin embargo, eso es porque = tiene una prioridad más alta que ,. Si se escribe como:

z = (1,3,4); 

entonces eso sería lo mismo que:

z = 4; 
+0

¡Precedencia! He estado alejado de C por un tiempo y he perdido mi hábito de poner entre paréntesis 'para estar a salvo'. – Jonathan

+0

No es una limitación de "declaraciones de declaración", es una limitación de declaración. La primera parte de 'for' no es una declaración en sí misma, por lo que el asunto no tiene nada que ver con declaración * statement * específicamente. – AnT

20

Si es necesario utilizar varias variables de distinto tipo en bucle for entonces se podría utilizar estructuras de la siguiente manera:

for(struct {int i; long i2;} x = {1, 1}; x.i2 < mid; x.i++, x.i2 = x.i * x.i) 
{ 
    cout << x.i2 << endl; 
} 

así que esto no es una limitación, solo use una sintaxis diferente.

+1

+1: Estaba a punto de publicar sobre esto ... Lástima que VC++ no lo admite ... – dalle

+1

Esto debería funcionar. C++ Standard lo permite. –

+0

Sí, * debería * funcionar, pero luego VC++ no cumple con C++. Probado con éxito con Comeau. – dalle

1

Bueno, hice un poco más de googlear, y creo que la respuesta para C++ es "para() las declaraciones son lugares muy especiales" Ick.

extractar de una especificación ISO:

for (for-init-statement conditionopt ; expressionopt) statement 

donde

for-init-statement: 
expression-statement 
simple-declaration 

y tienen que especificar que

[Note: a for-init-statement ends with a semicolon. ] 

Así que la especificación de sintaxis de C++. está específicamente pirateado, por lo que solo se permite una especificación decl (es decir, tipo) en la primera ranura. Parece que nuestros intentos de argumentar a partir de principios básicos estaban condenados. Gracias por todas las respuestas.

0

puedo ver por qué esperanza de que iba a funcionar, pero --- dado que incluso el uso de la herramienta de enseñanza de mente bastante simple que

for (i=0; i<max; i++){ 
    ... 
} 

es equivalente a

i=0; 
while (i<max){ 
    ... 
    i++; 
} 

que la sintaxis no funciona --- no puedo ver por qué esperaba que lo haría. EAch de los bits debe ser válido.

Cuestiones relacionadas