“Romper”, fuera de “si” statement?

¿Se puede romper una instrucción if o va a causar lockings? Estoy empezando a familiarizarme con C, pero esto parece controvertido. La primera imagen es de un libro en C (“Head First C”) y el fragmento muestra el código escrito por el personal de las clases de CS de Harvard. ¿Qué está pasando realmente y tiene algo que ver con los estándares de C?

los descansos no se rompen si las declaraciones.

El 15 de enero de 1990, el sistema telefónico de larga distancia de AT&T se estrelló y 60,000 personas perdieron su servicio telefónico. ¿La causa? Un desarrollador que trabaja en el código C utilizado en los intercambios intentó usar una break para salir de una sentencia if . Pero las break no se rompen if s. En su lugar, el progtwig omitió una sección completa de código e introdujo un error que interrumpió 70 millones de llamadas telefónicas durante nueve horas.

 for (size = 0; size < HAY_MAX; size++) { // wait for hay until EOF printf("\nhaystack[%d] = ", size); int straw = GetInt(); if (straw == INT_MAX) break; // add hay to stack haystack[size] = straw; } printf("\n"); 

break interactúa únicamente con el bucle o el interruptor de cierre más cercano, ya sea for , while o do .. while type. Con frecuencia se lo conoce como un goto disfrazado, ya que todos los bucles en C pueden de hecho transformarse en un conjunto de gotos condicionales:

 for (A; B; C) D; // translates to A; goto test; loop: D; iter: C; test: if (B) goto loop; end: while (B) D; // Simply doesn't have A or C do { D; } while (B); // Omits initial goto test continue; // goto iter; break; // goto end; 

La diferencia es, continue y break interactuar con tags virtuales colocadas automáticamente por el comstackdor. Esto es similar a lo que hace el return como usted sabe que siempre saltará hacia adelante en el flujo del progtwig. Los interruptores son un poco más complicados, generando matrices de tags y gotos computados, pero la forma en que Break trabaja con ellos es similar.

El error de progtwigción al que se refiere el aviso es una mala interpretación de la break como la interacción con un bloque envolvente en lugar de un bucle envolvente. Considerar:

 for (A; B; C) { D; if (E) { F; if (G) break; // Incorrectly assumed to break if(E), breaks for() H; } I; } J; 

Alguien pensó, dado tal código, que G causaría un salto a I , pero salta a J La función deseada se usaría if (!G) H; en lugar.

Este es en realidad el uso convencional de la sentencia break . Si la instrucción break no estaba anidada en un bloque if , el bucle for solo podría ejecutarse una vez.

MSDN muestra esto como su ejemplo para la instrucción break .

Creo que la pregunta es un poco confusa, por ejemplo, se puede interpretar como una pregunta sobre las mejores prácticas en la progtwigción de bucles con el interior. Entonces, trataré de responder esta pregunta con esta interpretación particular.

Si tiene dentro de un bucle, en la mayoría de los casos le gustaría saber cómo ha terminado el bucle. ¿Se “rompió” por el if o se terminó “naturalmente”? Entonces, su código de muestra puede ser modificado de esta manera:

 bool intMaxFound = false; for (size = 0; size < HAY_MAX; size++) { // wait for hay until EOF printf("\nhaystack[%d] = ", size); int straw = GetInt(); if (straw == INT_MAX) {intMaxFound = true; break;} // add hay to stack haystack[size] = straw; } if (intMaxFound) { // ... broken } else { // ... ended naturally } 

El problema con este código es que la instrucción if está enterrada dentro del cuerpo del bucle, y se necesita un cierto esfuerzo para localizarlo y entender lo que hace. Una variante más clara (incluso sin la instrucción break ) será:

 bool intMaxFound = false; for (size = 0; size < HAY_MAX && !intMaxFound; size++) { // wait for hay until EOF printf("\nhaystack[%d] = ", size); int straw = GetInt(); if (straw == INT_MAX) {intMaxFound = true; continue;} // add hay to stack haystack[size] = straw; } if (intMaxFound) { // ... broken } else { // ... ended naturally } 

En este caso, puede ver claramente (solo mirando el "encabezado" del bucle) que este bucle puede terminar prematuramente. Si el cuerpo del bucle es un texto de varias páginas, escrito por otra persona, agradecería a su autor por ahorrar su tiempo.

ACTUALIZAR:

Gracias a SO: acaba de sugerir la pregunta ya respondida sobre el locking de la red telefónica de AT&T en 1990. Se trata de una decisión arriesgada de los creadores de C de usar un solo break palabra reservado para salir de ambos bucles y switch .

De todos modos, esta interpretación no se sigue del código de muestra en la pregunta original, así que estoy dejando mi respuesta como está.

Como ya se mencionó, la instrucción break solo funciona con interruptores y bucles . Aquí hay otra manera de lograr lo que se pide. Estoy reproduciendo https://stackoverflow.com/a/257421/1188057 como nadie más lo mencionó. Es solo un truco que involucra el bucle do-while.

 do { // do something if (error) { break; } // do something else if (error) { break; } // etc.. } while (0); 

Aunque preferiría el uso de goto-statement .