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 .

¿Fue útil?

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 que break , 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 un continue 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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top