2009-12-05 12 views
14

Un cliente realizó recientemente un análisis estático del código C de mi empleador y nos dio los resultados. Entre los parches útiles se encontraba la solicitud para cambiar la famosa macro do { ... } while(0) al do { ... } while(0,0). Entiendo lo que está haciendo su parche (usando el operador de secuencia return evalúe el valor del segundo "0", por lo que el efecto es el mismo) pero no está claro por qué favorecen el segundo formulario sobre el primer formulario .En macros C, ¿debería uno preferir hacer {...} mientras que (0,0) más hacer {...} mientras (0)?

¿Existe una razón legítima por la que uno debería preferir la segunda forma de la macro o el análisis estático de nuestro cliente es excesivamente pedante?

+5

La herramienta de análisis estático de su cliente era demasiado, eso es seguro. –

+7

Me gustaría "demasiado demasiado redundante". –

+3

No puedo pensar en ninguna razón para hacer esto. Tal vez alguna herramienta se queja con una condición while (0) en la línea de "esto nunca sucederá", pero cualquier herramienta debería 1) reconocer que esta es una expresión muy común en C con macros y 2) diferenciar entre do ... mientras (0) y mientras (0) {}. ¿Les has pedido un razonamiento? –

Respuesta

11

Bueno, voy a ir por respuesta:

¿Hay una razón legítima por la que se debe preferir la segunda forma de la macro ...?

No. No existe un motivo legítimo. Ambos siempre evalúan como falso, y cualquier compilador decente probablemente convertirá el segundo en el primero en el conjunto de todos modos. Si hubo alguna razón para que fuera inválida en algunos casos, C ha existido el tiempo suficiente para que esa razón sea descubierta por gurús mayores que yo.

Si te gusta el código que te hace mirar a tu lechuza, utiliza while(0,0). De lo contrario, use lo que usa el resto del mundo de programación de C y dígale a la herramienta de análisis estático de su cliente.

+0

No evalúa a nada; y do-loop no es una expresión y no tiene ningún valor. Intente asignarlo int x = macro(); y no se puede compilar. – Clifford

+1

Me refiero a la evaluación de '0' contra' 0,0', no del bucle 'do {} while (0)' en general. –

+0

Ok; Todavía estaba tratando de comprender el beneficio como un todo. – Clifford

11

Sólo una conjetura en cuanto a por qué podrían sugerir el uso de

do { ... } while(0,0) 

sobre

do { ... } while(0) 

A pesar de que no hay ninguna diferencia de comportamiento y debería haber ninguna diferencia en el costo de tiempo de ejecución entre los dos.

Supongo que la herramienta de análisis estático se queja de que el ciclo while está controlado por una constante en el caso más simple y no cuando se usa 0,0. La sugerencia del cliente probablemente sea solo para que no obtengan un montón de falsos positivos de la herramienta.

Por ejemplo, ocasionalmente encuentro situaciones en las que quiero tener una sentencia condicional controlada por una constante, pero el compilador se queja con una advertencia acerca de una expresión condicional que evalúa una constante. Luego tengo que saltar algunos aros para que el compilador deje de quejarse (ya que no me gusta tener advertencias espurias).

La sugerencia de su cliente es uno de los aros que he utilizado para silenciar esa advertencia, aunque en mi caso no estaba controlando un bucle while, era para hacer frente a una afirmación de "siempre falla". Ocasionalmente, tendré un área de código que nunca debería ejecutarse (tal vez el caso predeterminado de un interruptor). En esa situación, que podría tener una afirmación de que siempre falla con algún mensaje:

assert(!"We should have never gotten here, dammit..."); 

Pero, al menos un compilador que utilice emite una advertencia acerca de la expresión siempre que evalúan como false. Sin embargo, si lo cambio a:

assert(("We should have never gotten here, dammit...", 0)); 

La advertencia desaparece, y todo el mundo está contento. Supongo que incluso la herramienta de análisis estático de tu cliente también lo sería.Tenga en cuenta que por lo general oculto ese poco de saltar aro detrás de una macro como:

#define ASSERT_FAIL(x) assert(((x), 0)) 

Podría ser agradable ser capaz de decirle al proveedor de herramientas para solucionar el problema, pero puede haber casos legítimos en el que realmente no quieren para diagnosticar un bucle controlado por una expresión booleana constante. Por no mencionar el hecho de que, incluso si convence a un vendedor de herramientas para que haga ese cambio, eso no le ayudará durante el próximo año o así que le tome realmente arreglarlo.

+2

+1 Esto podría ser, pero si este es el caso, estas advertencias solo deberían deshabilitarse con las opciones de línea de comando. ¿Por qué saltar a través de aros cuando puedes simplemente desactivar los aros que no son necesarios? –

+1

Bueno, por un lado, hurzing alrededor con las opciones de compilador o herramienta puede considerarse una forma de salto de aro. Atornillarse con los makefiles o cualquier control que haga su compilación es a menudo mucho más magia negra que el hackers de preprocesador de C (y eso es mucho decir). Por otro lado, es posible que no desee que la advertencia se deshabilite para todo, tal vez solo para las macros de depuración que parecen necesitar estos trucos estúpidos. –

+0

+1 Esta debería ser la respuesta aceptada. – Calmarius

8

El uso de while (0,0) impide que el compilador de Microsoft genere una advertencia sobre una condición que es una constante (Advertencia C4127).

Cuando esta advertencia está habilitada (por ejemplo, con/W4 o/Muro), se puede cerrar caso por caso con este pequeño truco (see this other thread).

Cuestiones relacionadas