En C / C ++, ¿por qué el do while (expresión); necesito un semi colon?

Mi suposición es que simplemente hizo que el análisis sintáctico sea más fácil, pero no puedo ver exactamente por qué.

Entonces, qué tiene esto …

do { some stuff } while(test); more stuff 

eso es mejor que …

 do { some stuff } while(test) more stuff 

Es porque las instrucciones while son válidas dentro de un ciclo do-while.

Considere los diferentes comportamientos si el punto y coma no fue requerido:

 int x = 10; int y = 10; do while(x > 0) x--; while(x = y--); 

Porque estás terminando la statement. Una instrucción finaliza con un bloque (delimitado por llaves) o con un punto y coma. “haz esto mientras esto” es una statement única, y no puede terminar con un bloque (porque termina con el “while”), por lo que necesita un punto y coma al igual que cualquier otra instrucción.

Si echas un vistazo a la gramática C ++, verás que las declaraciones de iteración se definen como

while ( condición ) statement

para la sentencia ( for-init-statement -opt ; expression -opt )

do statement while ( expresión );

Tenga en cuenta que solo la instrucción do-while tiene una ; al final. Entonces, la pregunta es por qué el do-while es tan diferente del rest que necesita ese extra ; .

Echemos un vistazo más de cerca: tanto for regular como for while finalice con una statement . Pero do-while termina con una expresión de control encerrada en () . La presencia de ese adjunto () ya permite al comstackdor encontrar inequívocamente el final de la expresión de control: el cierre externo ) designa dónde termina la expresión y, por lo tanto, dónde finaliza toda la instrucción do-while . En otras palabras, la terminación ; es de hecho redundante.

Sin embargo, en la práctica eso significaría que, por ejemplo, el siguiente código

 do { /* whatever */ } while (i + 2) * j > 0; 

si bien es válido desde el punto de vista gtwigtical, realmente sería analizado como

 do { /* whatever */ } while (i + 2) *j > 0; 

Esto es formalmente correcto, pero no es realmente intuitivo. Supongo que por tales razones se decidió agregar un terminador más explícito a la statement do-while : un punto y coma. Por supuesto, para la respuesta de @Joe White también hay consideraciones de consistencia simple y simple: todas las declaraciones ordinarias (no compuestas) en C terminan con a ; .

Si bien no sé la respuesta, la coherencia parece ser el mejor argumento. Cada grupo de instrucciones en C / C ++ es terminado por

  1. Un punto y coma
  2. Un aparato ortopédico

¿Por qué crear una construcción que no hace ninguna?

Consistencia del enunciado de control de flujo

Teniendo en cuenta la coherencia …

 if (expr) statement; do statement; while (expr); for (expr; expr; expr) statement; while (expr) statement; 

… todas estas construcciones de control de flujo, terminan con un punto y coma.

Pero, contrarrestando eso, podemos observar que de los formularios de instrucción de bloque, solo do while está delimitado por punto y coma:

 if (expr) { ... } do { ... } while (expr); for (expr; expr; expr) { } while (expr) { } 

Entonces tenemos ‘;’ o ‘}’, pero nunca un “descubierto” ‘)’.

Consistencia de los delimitadores de enunciados

Al menos podemos decir que cada enunciado debe estar delimitado por ; o } , y visualmente eso nos ayuda a distinguir las declaraciones.

Si no se requirió punto y coma, considere:

 do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4; 

Es muy difícil resolverlo visualmente con las declaraciones distintas:

 do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4; 

Por contraste, lo siguiente se resuelve más fácilmente como a ; Inmediatamente después de un while condición te dice que busques al revés para do , y que la siguiente afirmación no está conectada a eso while :

 do statement1; while (expr1); statement2; do ; while (expr2); statement3; while (expr3) statement4; 

¿Importa, dado que las personas sangran su código para hacer que el flujo sea comprensible? Sí porque:

  • las personas a veces cometen errores (o los tienen transitoriamente mientras se masajea el código) y si se destaca visualmente eso significa que se solucionará más fácilmente, y
  • las sustituciones de macros pueden juntar muchas declaraciones en una línea, y de vez en cuando necesitamos verificar visualmente la salida del preprocesador mientras solucionamos problemas o hacemos QA.

Implicaciones para el uso del preprocesador

También vale la pena destacar el famoso preprocesador do-while:

 #define F(X) do { fn(X); } while (false) 

Esto puede ser sustituido de la siguiente manera:

 if (expr) F(x); else x = 10; 

… cede …

 if (expr) do ( fn(x); } while (false); else x = 10; 

Si el punto y coma no era parte de la instrucción do while , entonces la instrucción if se interpretaría como:

 if (expr) do-while-statement ; // empty statement else x = 10; 

… y, debido a que hay dos declaraciones después del if , se considera completo, lo que deja la statement else sin igual.

C tiene un punto y coma (mientras que Pascal está separado por punto y coma). Sería inconsistente dejar caer el punto y coma allí.

Yo, francamente, odio la reutilización del tiempo para el ciclo do. Creo que repetir, hasta que hubiera sido menos confuso. Pero es lo que es.

En C / C ++, los espacios en blanco no contribuyen a la estructura (como, por ejemplo, en python). En C / C ++ las declaraciones deben terminarse con un punto y coma. Esto está permitido:

 do { some stuff; more stuff; even more stuff; } while(test); 

Mi respuesta es que el comstackdor puede confundirse cuando no incluimos el punto y coma en la terminación de do.....while(); lazo. Sin esto, no está claro sobre:

  1. cuando el do termina?
  2. Si el tiempo puede, un bucle separado seguido inmediatamente después de do loop.

Es por eso que incluimos el punto y coma al final de do......while bucle, para indicar que el bucle termina aquí si la condición es falsa.