loop - while in c
do{…} while(0)-¿para qué sirve? (5)
Ayuda a agrupar varias declaraciones en una sola, de modo que una macro similar a una función se puede utilizar como una función. Supongamos que tienes
#define FOO(n) foo(n);bar(n)
y lo hace
void foobar(int n){
if (n)
FOO(n);
}
entonces esto se expande a
void foobar(int n){
if (n)
foo(n);bar(n);
}
Observe que la segunda llamada (barra (n)) ya no forma parte de la instrucción if.
Envuelva ambos en do {} while (0), y también puede usar la macro en una sentencia if.
Posible duplicado:
¿Por qué a veces hay sentencias do / while y if / else en las macros C / C ++ sin sentido?
He estado viendo esa expresión por más de 10 años. He estado tratando de pensar para qué sirve. Como lo veo principalmente en #defines, asumo que es bueno para la declaración de variables de alcance interno y para usar cortes (en lugar de gotos).
¿Es bueno para cualquier otra cosa? ¿Lo usas?
En general, do
/ while
es bueno para cualquier tipo de construcción de bucle donde se debe ejecutar el bucle al menos una vez. Es posible emular este tipo de bucle a través de un while
directo o incluso un bucle for
, pero a menudo el resultado es un poco menos elegante. Admito que las aplicaciones específicas de este patrón son bastante raras, pero existen. Uno que viene a la mente es una aplicación de consola basada en menú:
do {
char c = read_input();
process_input(c);
} while (c != ''Q'');
Es interesante observar la siguiente situación en la que el bucle do {} while (0) no funcionará para usted:
Si desea una macro similar a una función que devuelva un valor, entonces necesitará una expresión de declaración : ({stmt; stmt;}) en lugar de do {} while (0):
#include <stdio.h>
#define log_to_string1(str, fmt, arg...) /
do { /
sprintf(str, "%s: " fmt, "myprog", ##arg); /
} while (0)
#define log_to_string2(str, fmt, arg...) /
({ /
sprintf(str, "%s: " fmt, "myprog", ##arg); /
})
int main() {
char buf[1000];
int n = 0;
log_to_string1(buf, "%s/n", "No assignment, OK");
n += log_to_string1(buf + n, "%s/n", "NOT OK: gcc: error: expected expression before ''do''");
n += log_to_string2(buf + n, "%s/n", "This fixes it");
n += log_to_string2(buf + n, "%s/n", "Assignment worked!");
printf("%s", buf);
return 0;
}
Es una forma de simplificar la comprobación de errores y evitar el anidado profundo si. Por ejemplo:
do {
// do something
if (error) {
break;
}
// do something else
if (error) {
break;
}
// etc..
} while (0);
Es la única construcción en C que puede usar para #define
una operación de múltiples estados, poner un punto y coma después, y aún usar dentro de una declaración if
. Un ejemplo podría ayudar:
#define FOO(x) foo(x); bar(x)
if (condition)
FOO(x);
else // syntax error here
...;
Incluso el uso de llaves no ayuda:
#define FOO(x) { foo(x); bar(x); }
Usar esto en una declaración if
requeriría que omitas el punto y coma, que es contraintuitivo:
if (condition)
FOO(x)
else
...
Si define FOO así:
#define FOO(x) do { foo(x); bar(x); } while (0)
entonces lo siguiente es sintácticamente correcto:
if (condition)
FOO(x);
else
....