¿Por qué las expresiones vacías son legales en C / C ++?

int main() { int var = 0;; // Typo which compiles just fine } 

Esta es la forma en que C y C ++ expresan NOP .

De qué otra manera podría assert(foo == bar); comstackr hasta nada cuando se define NDEBUG ?

Obviamente, así podemos decir cosas como

 for(;;) { // stuff } 

¿Quién podría vivir sin eso?

No soy diseñador de idiomas, pero la respuesta que daré es “¿por qué no?” Desde la perspectiva del diseño del lenguaje, uno quiere que las reglas (es decir, la gramática) sean lo más simples posible.

Sin mencionar que las “expresiones vacías” tienen usos, es decir,

para (i = 0; i

Will dead-wait (no es un buen uso, pero un uso, no obstante).

EDITAR: Como se señaló en un comentario a esta respuesta, cualquier comstackdor que merezca la pena probablemente no esté ocupado esperando en este ciclo y lo optimice. Sin embargo, si hubiera algo más útil en el encabezado en sí mismo (aparte de i ++), que he visto hecho (extrañamente) con el cruce de estructuras de datos, entonces me imagino que todavía podría construir un bucle con un cuerpo vacío (usando / abusando de la construcción “para”).

Honestamente, no sé si este es el verdadero motivo, pero creo que algo que tiene más sentido es pensarlo desde el punto de vista de un implementador de comstackdores.

Grandes porciones de comstackdores se construyen con herramientas automatizadas que analizan clases especiales de gramáticas. Parece muy natural que las gramáticas útiles permitan declaraciones vacías. Parece un trabajo innecesario detectar ese “error” cuando no cambia la semántica de su código. La instrucción vacía no hará nada, ya que el comstackdor no generará código para esas declaraciones.

Me parece que esto es solo el resultado de “No arregles algo que no está roto” …

Quieres ser capaz de hacer cosas como

 while ( fnorble(the_smurf) == FAILED ) ; 

y no

 while ( fnorble(the_smurf) == FAILED ) do_nothing_just_because_you_have_to_write_something_here(); 

¡Pero! Por favor, no escriba la statement vacía en la misma línea, como esta:

 while ( fnorble(the_smurf) == FAILED ); 

Esa es una muy buena manera de confundir al lector, ya que es fácil pasar por alto el punto y coma y, por lo tanto, pensar que la siguiente fila es el cuerpo del bucle. Recuerde: la progtwigción se trata realmente de comunicación, no con el comstackdor, sino con otras personas que leerán su código. (¡O contigo mismo, tres años después!)

OK, agregaré esto al peor de los casos que puedas usar:

 for (int yy = 0; yy < nHeight; ++yy) { for (int xx = 0; xx < nWidth; ++xx) { for (int vv = yy - 3; vv <= yy + 3; ++vv) { for (int uu = xx - 3; uu <= xx + 3; ++uu) { if (test(uu, vv)) { goto Next; } } } Next:; } } 

El caso más común es probablemente

 int i = 0; for (/* empty*/; i != 10; ++i) { if (x[i].bad) break; } if (i != 10) { /* panic */ } 

Cuando usas ‘;’ por favor también ten en cuenta una cosa. Esto esta bien:

 a ? b() : c(); 

Sin embargo, esto no comstackrá:

 a ? b() : ; ; 
 while(1){ ; /* do nothing */ } 

Hay momentos en que quieres sentarte y no hacer nada. Una aplicación incrustada por evento / interrupción o cuando no desea que una función salga, como cuando se configuran subprocesos y se espera el primer cambio de contexto.

ejemplo: http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523

Ya hay muchas buenas respuestas pero no hemos visto la muestra del entorno productivo.

Aquí está la implementación de strlen de strlen :

 size_t strlen(const char *str) { const char *s; for (s = str; *s; ++s) ; return (s - str); }