¿Cuál es el total & # 8220; para & # 8221; sintaxis de bucle en C?
Pregunta
He visto algunos bucles for
muy extraños al leer el código de otras personas. Intenté buscar una explicación de sintaxis completa para el bucle for
en C
pero es muy difícil porque la palabra " para
" ; aparece en oraciones no relacionadas que hacen que la búsqueda sea casi imposible para Google de manera efectiva.
Esta pregunta me vino a la mente después de leer este hilo que me hizo sentir curiosidad nuevamente.
El para
aquí:
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);
En la condición intermedia hay una coma que separa las dos piezas de código, ¿qué hace esta coma? Entiendo la coma del lado derecho, ya que hace que a > > = 1
y b < < = 1
.
Pero dentro de una condición de salida de bucle, ¿qué sucede? ¿Sale cuando p == 0
, cuando a == 1
o cuando ambos suceden?
Sería genial si alguien pudiera ayudarme a entender esto y tal vez señalarme en la dirección de una descripción completa de la sintaxis de bucle for
.
Solución
La coma no es exclusiva de for loops; es el operador de coma.
x = (a, b);
hará primero a, luego b, luego establecerá x en el valor de b.
La sintaxis for es:
for (init; condition; increment)
...
Que es algo (ignorando continue
y break
por ahora) equivalente a:
init;
while (condition) {
...
increment;
}
Entonces, su ejemplo de bucle for es (nuevamente ignorando continue
y break
) equivalente a
p=0;
while (p+=(a&1)*b,a!=1) {
...
a>>=1,b<<=1;
}
Que actúa como si fuera (nuevamente ignorando continue
y break
):
p=0;
while (true) {
p+=(a&1)*b;
if (a == 1) break;
...
a>>=1;
b<<=1;
}
Dos detalles adicionales del ciclo for que no estaban en la conversión simplificada a un ciclo while anterior:
- Si se omite la condición, siempre es
true
(lo que da como resultado un bucle infinito a menos quebreak
,goto
o algo más se rompa el bucle). - Un
continue
actúa como si fuera un goto a una etiqueta justo antes del incremento, a diferencia de uncontinue
en el ciclo while que omitiría el incremento.
Además, un detalle importante sobre el operador de coma: es un punto de secuencia, como & amp; & amp;
y ||
(por eso puedo dividirlo en declaraciones separadas y mantener su significado intacto).
Cambios en C99
El estándar C99 introduce un par de matices no mencionados anteriormente en esta explicación (que es muy bueno para C89 / C90).
Primero, todos los bucles son bloques por derecho propio. Efectivamente,
for (...) { ... }
está envuelto en un par de llaves
{
for (...) { ... }
}
El estándar dice:
ISO / IEC 9899: 1999 & # 167; 6.8.5 Declaraciones de iteración
& # 182; 5 Una declaración de iteración es un bloque cuyo alcance es un subconjunto estricto del alcance de su bloque de cerramiento. El cuerpo del bucle también es un bloque cuyo alcance es un subconjunto estricto del alcance de la declaración de iteración.
Esto también se describe en la Justificación en términos del conjunto adicional de llaves.
En segundo lugar, la parte init
en C99 puede ser una declaración (única), como en
for (int i = 0; i < sizeof(something); i++) { ... }
Ahora el 'bloque envuelto alrededor del bucle' entra en sí mismo; explica por qué no se puede acceder a la variable i
fuera del bucle. Puede declarar más de una variable, pero todas deben ser del mismo tipo:
for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }
El estándar dice:
ISO / IEC 9899: 1999 & # 167; 6.8.5.3 La declaración for
La declaración
for ( clause-1 ; expression-2 ; expression-3 ) statement
se comporta de la siguiente manera: La expresión expresión-2 es la expresión de control que es evaluado antes de cada ejecución del cuerpo del bucle. La expresión expresión-3 es evaluado como una expresión vacía después de cada ejecución del cuerpo del bucle. Si la cláusula-1 es un declaración, el alcance de cualquier variable que declare es el resto de la declaración y el ciclo completo, incluidas las otras dos expresiones; se alcanza en el orden de ejecución antes de la primera evaluación de la expresión controladora. Si la cláusula-1 es una expresión, es evaluado como una expresión vacía antes de la primera evaluación de la expresión de control. 133)
Se pueden omitir tanto la cláusula-1 como la expresión-3. Una expresión-2 omitida se reemplaza por una constante diferente de cero.
133) Por lo tanto, la cláusula-1 especifica la inicialización del bucle, posiblemente declarando una o más variables para su uso en el lazo; la expresión de control, expresión-2, especifica una evaluación realizada antes de cada iteración, tal que la ejecución del ciclo continúa hasta que la expresión se compare igual a 0; y expresión-3 especifica una operación (como el incremento) que se realiza después de cada iteración.
Otros consejos
La coma simplemente separa dos expresiones y es válida en cualquier lugar de C donde se permita una expresión normal. Estos se ejecutan en orden de izquierda a derecha. El valor de la expresión más a la derecha es el valor de la expresión general.
Los bucles for
constan de tres partes, cualquiera de las cuales también puede estar vacía; uno (el primero) se ejecuta al principio y uno (el tercero) al final de cada iteración. Estas partes generalmente inicializan e incrementan un contador, respectivamente; pero pueden hacer cualquier cosa.
La segunda parte es una prueba que se ejecuta al comienzo de cada ejecución. Si la prueba arroja false
, el ciclo se cancela. Eso es todo lo que hay que hacer.
El estilo C para el bucle consta de tres expresiones:
for (initializer; condition; counter) statement_or_statement_block;
- El inicializador se ejecuta una vez, cuando comienza el ciclo.
- La condición se verifica antes de cada iteración. El ciclo se ejecuta siempre que se evalúe como verdadero.
- El contador se ejecuta una vez después de cada iteración.
Cada una de estas partes puede ser una expresión válida en el lenguaje en el que escribe el bucle. Eso significa que pueden usarse de manera más creativa. Cualquier cosa que desee hacer de antemano puede ir al inicializador, cualquier cosa que desee hacer en el medio puede ir a la condición o al contador, hasta el punto en que el bucle ya no tiene cuerpo.
Para lograr eso, el operador de coma es muy útil. Le permite encadenar expresiones para formar una sola expresión nueva. La mayoría de las veces se usa de esa manera en un ciclo for, las otras implicaciones del operador de coma (por ejemplo, consideraciones de asignación de valores) juegan un papel menor.
Aunque puedes hacer cosas inteligentes usando la sintaxis de forma creativa, me mantendría alejado de eso hasta que encuentre una realmente buena razón para hacerlo. Jugar golf de código con bucles for hace que el código sea más difícil de leer y comprender (y mantener).
La wikipedia también tiene un buen artículo sobre el bucle for .
Todo es opcional en un bucle for
. Podemos inicializar más de una variable, podemos verificar más de una condición, podemos iterar más de una variable usando el operador de coma.
El siguiente bucle for
lo llevará a un bucle infinito. Tenga cuidado al verificar la condición.
for(;;)
Konrad mencionó el punto clave que me gustaría repetir: el valor de la expresión más a la derecha es el valor de la expresión general.
Un compilador Gnu declaró esta advertencia cuando puse dos pruebas en la condición """ sección del bucle for
warning: left-hand operand of comma expression has no effect
Lo que realmente pretendía para la "condición" fueron dos pruebas con un & amp; & amp; & amp; " Entre. Según la declaración de Konrad, solo la prueba a la derecha de la coma afectaría la condición.
el bucle for es ejecución durante un tiempo particular para (;;)
el syntex para for loop
para (;;)
O
para (inicializador; condición; contador)
por ejemplo (rmv = 1; rmv < = 15; rmv ++)
ejecución hasta 15 veces en bloque
1.primero inicializa el valor porque comienza el valor
(por ejemplo) rmv = 1 o rmv = 2
2.segunda declaración es probar que la condición es verdadera o falsa, la condición verdadera no. de tiempo de ejecución del bucle for y la condición es falsa terminar para el bloque,
por ejemplo, i = 5; i < = 10 la condición es verdadera
i=10;i<10 the condition is false terminate for block,
3. el tercero es aumentar o disminuir
(por ejemplo) rmv ++ o ++ rmv