#include <iostream> using namespace std; int main(int argc, char *argv[]) { int n = 12; int q = (n + 3) / 4; cout << q; cout << ' '; cout << n%4; cout << ' '; switch (n % 4) { case 0: cout << n; cout << ' '; do { n++; cout << n; cout << ' '; case 3: n++; cout << n; cout << ' '; case 2: n++; case 1: n++; cout <<n; cout << ' '; } while (--q > 0); } cout << n; }Con el código anterior, obtuve lo siguiente:
3 0 12 13 14 16 17 18 20 21 22 24 24No estoy familiarizado con el lenguaje C++.
¿Por qué falla en la segunda y tercera iteración del ciclo while?
¿La instrucción switch case guarda el valor inicial de n%4 y lo aplica durante el ciclo do-while?
las etiquetas de las cajas son solo etiquetas. Dentro de su declaración de cambio, el código se ejecuta secuencialmente porque no hay una declaración de salto como, por ejemplo, romper, ir a o regresar.
Para que quede más claro, puede reescribir la declaración de cambio de la siguiente manera cuando la expresión n % 4 es igual a 0.
goto Label0; { Label0: cout << n; cout << ' '; do { n++; cout << n; cout << ' '; n++; cout << n; cout << ' '; n++; n++; cout <<n; cout << ' '; } while (--q > 0); }Entonces, si ejecutará su programa con la modificación
#include <iostream> using namespace std; int main() { int n = 12; int q = (n + 3) / 4; cout << q; cout << ' '; cout << n%4; cout << ' '; goto Label0; { Label0: cout << n; cout << ' '; do { n++; cout << n; cout << ' '; n++; cout << n; cout << ' '; n++; n++; cout <<n; cout << ' '; } while (--q > 0); } cout << n; return 0; }obtendrás el mismo resultado.
3 0 12 13 14 16 17 18 20 21 22 24 24Si, por ejemplo, insertará una declaración de interrupción antes de la etiqueta case 2 como
switch (n % 4) { case 0: cout << n; cout << ' '; do { n++; cout << n; cout << ' '; case 3: n++; cout << n; cout << ' '; break; case 2: n++; case 1: n++; cout <<n; cout << ' '; } while (--q > 0); }entonces esta sentencia break está de hecho dentro de la sentencia compuesta de la sentencia do-while. Por lo tanto, la instrucción do-while se interrumpirá y el control pasará al punto anterior a la llave de cierre de la instrucción switch. Entonces, la declaración de cambio también se interrumpirá.
En este caso, la salida del programa será
3 0 12 13 14 14Los "casos de cambio" siempre fallan, a menos que break explícitamente el interruptor.
La construcción switch-case es esencialmente un grupo glorificado de goto s, pero más robusto que uno construido manualmente.
(Su código parece una versión ligeramente mutada del legendario "dispositivo de Duff", una construcción de desenrollado de bucles que ha confundido a generaciones de programadores de C).
Traducido a "código Goto" no estructurado, su interruptor es lógicamente equivalente a
int x = n % 4; if (x == 0) goto zero; if (x == 1) goto one; if (x == 2) goto two; if (x == 3) goto three; zero: cout << n << ' '; loop: n++; cout << n << ' '; three: n++; cout << n << ' '; two: n++; one: n++; cout << n << ' '; if (--q > 0) goto loop;pero el compilador podría ser capaz de crear un código más eficiente a partir del interruptor que esa serie de condicionales, mediante el uso de una tabla de salto real.
Nota al pie: gcc en realidad le permite usar etiquetas como valores y saltar a ellas, por lo que podría crear exactamente esa tabla usted mismo;
void* table = { &&zero, &&one, &&two, &&three }; goto *table[n % 4]; zero: cout << n << ' '; loop: n++; cout << n << ' '; three: n++; cout << n << ' '; two: n++; one: n++; cout << n << ' '; if (--q > 0) goto loop;(No es que debas , pero podrías . Un buen compilador compilará tu interruptor a algo similar a esto si es beneficioso, sobre lo que sabe más que un simple humano).