c++ - una - que es declaracion de variables
¿Por qué no puedo poner una declaración de variable en la porción de prueba de un ciclo while? (6)
Obviamente, puedes poner una declaración de variable en un ciclo for:
for (int i = 0; ...
y me he dado cuenta de que puedes hacer lo mismo en if y cambiar las declaraciones también:
if ((int i = f()) != 0) ...
switch (int ch = stream.get()) ...
Pero cuando trato de hacer lo mismo en un ciclo while:
while ((int ch = stream.get()) != -1) ...
El compilador (VC ++ 9.0) no le gusta en absoluto.
¿Es este comportamiento obediente? ¿Hay alguna razón para ello?
EDIT : encontré que puedo hacer esto:
while (int ch = stream.get() != -1) ...
pero debido a las reglas de precedencia, eso se interpreta como:
while (int ch = (stream.get() != -1)) ...
que no es lo que quiero
Esto no parece ser un comportamiento conforme. La parte 6.5.1.2 del estándar establece:
Cuando la condición de una sentencia while es una declaración, el alcance de la variable que se declara se extiende desde su punto de declaración (3.3.1) hasta el final de la instrucción while. Una declaración de tiempo de la forma
while (T t = x) instrucción
es equivalente a
label:
{ //start of condition scope
T t = x;
if (t) {
statement
goto label;
}
}
Por lo tanto, en su ejemplo, ch debe declararse dentro del alcance del bucle y funcionar correctamente (recreándose con cada iteración de bucle). La razón del comportamiento observado probablemente se debe a que el compilador no analizó correctamente la variable y luego la declaró varias veces.
La gramática para una condición en el estándar ''03 se define de la siguiente manera:
condition:
expression
type-specifier-seq declarator = assignment-expression
Lo anterior solo permitirá condiciones tales como:
if ( i && j && k ) {}
if ( (i = j) ==0 ) {}
if ( int i = j ) {}
El estándar permite que la condición declare una variable, sin embargo, lo han hecho agregando una nueva regla gramatical llamada ''condición'' que puede ser una expresión o un declarador con un inicializador. El resultado es que el hecho de que estés en la condición de un if
, for
, while
o switch
no significa que puedas declarar una variable dentro de una expresión.
Puede ser porque el contenido de la cláusula while se evalúa en cada ciclo, por lo que trataría de declarar "ch" varias veces.
Los ejemplos de if, switch y for loop que usted presente tendrán una "ch" definida solo una vez.
Puede poner una declaración de variable en la expresión de prueba de un ciclo while. Lo que no puedes hacer es poner una declaración en otras expresiones. Por ejemplo, en la expresión a + b + c, no puede reemplazar b por int i = f()
. Y el mismo asidero para la expresión (a)
; no puede insertar int i=f()
para obtener una expresión (int i=f())
.
Entonces, en while (int i = foo())
, los corchetes exteriores son parte de la sentencia while, y no de la expresión de texto, y todo es legal. En while ((int i = foo()))
, los paréntesis más externos siguen siendo parte de la sentencia while. La expresión de prueba tendría la forma "(" expr ")"
, y terminaría con un error de sintaxis.
Prueba esto no funciona
while (int ch = stream.get(), ch != -1) ...
Nunca lo intenté, pero si el comentario en su edición es correcto, esto debería funcionar.
VS 2005 ni siquiera lo compilará.
El problema es que el estándar te permite una declaración entre paréntesis. Lo que quiere hacer es obtener una declaración como parte de la expresión, que es algo que el estándar no le permitirá hacer.
while () puede tener una de dos sintaxis: while (<declaration>) o while (<expression>). La declaración usa "=", y se parece a la expresión, pero es una entidad sintáctica diferente.
Cuando escribes
while(int i = 1) {
}
, eso está perfectamente bien. "int i = 1" es una declaración. Sin embargo, lo que quieres es
while ( (int i = 1) + 3) {
}
Este es un animal muy diferente. Desea una expresión dentro de while (), donde uno de los términos de la expresión es una declaración. Ahora, la declaración es una declaración, y como tal no puede ser parte de la expresión. Es por eso que lo que debes hacer no se puede hacer.
(Después de escribir toda la diatriba, noté que otras 2 personas escribieron lo mismo. Bueno, cuanto más, mejor. La respuesta aceptada sigue siendo incorrecta en el momento de mi redacción).