c++ - usando - ¿Es útil el `warning C4127`(la expresión condicional es constante) alguna vez útil?
if c++ (2)
No creo que alguna vez sea útil. Por el contrario, hay más falsos positivos que solo el lenguaje do .. while(0)
. Piensa en constructos como
if(sizeof(long) == 8) { /* ... */ }
if(SOME_CONSTANT_MACRO) { /* ... */ }
El primero no puede ser reemplazado por #if
directivas #if
, el segundo podría, pero algunas pautas de estilo de codificación prefieren la versión if
comprobación de sintaxis todavía se realiza para el código muerto (que no está muerto en otras plataformas o con otra configuración de tiempo de compilación) y algunos lo encuentran mejor para leer.
Las advertencias (distintas de las requeridas por la norma, la mayoría de las cuales deben tratarse como errores) generalmente se emiten para un código que es válido pero es probable que haga algo más de lo que se pretende. if(0)
o cosas como esta parecen ridículas, pero no parezca que se pretendiera algo más que "sintaxis, verifique este código muerto". Puede confundir al lector, pero es inequívoco, y no veo cómo esto podría suceder accidentalmente.
De los ejemplos dados hasta ahora (no tengo MSVC para probar por mi cuenta), parece que la advertencia es para expresiones constantes en el sentido del lenguaje C (es decir, no es algo que se pueda plegar de manera constante sino sintácticamente). no es una expresión constante), por lo que no se emite para if(array)
o if(function)
(lo que, por ejemplo, gcc -Wall
advierte porque es probable que sea una llamada a la función).
while(0,0)
es peor, en mi opinión, desencadena una advertencia con gcc -Wall
para un lado izquierdo de un operador de coma sin efectos secundarios, una advertencia que puedo imaginar que es ocasionalmente útil (y que generalmente es fácil de evitar). Esta advertencia desaparece con while((void)0,0)
.
Sugiero apagar la advertencia.
Al responder a this publicación, sugerí usar do {...} while(0)
para macros multilínea.
En MSVC, encontré este código arroja:
warning C4127: conditional expression is constant
Para hacer que el código sea libre de advertencias, debo elegir una de estas alternativas feas:
Opción 1
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#endif
code_using_macro_that_generates_C4217;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
opcion 2
Define mis macros como:
#define MULTI_LINE_MACRO do { ... } while(0,0)
o
#define MULTI_LINE_MACRO do { ... } while((void)0,0)
También llamado "búho" por algunos programadores ya que (0,0)
parece a un búho.
Opcion 3
Defina una nueva macro WHILE_0 que no genere una advertencia y la use en lugar de while(0)
Problema
Creo que todas las alternativas son más o menos horribles. ¿Por qué MSVC genera esta advertencia para el código aparentemente correcto y me motiva a agregar algo de fealdad a mi código para mantener el aviso de código libre?
Creo que las expresiones constantes en condicionales son perfectamente válidas y útiles, en particular en construcciones basadas en la capacidad del compilador para optimizar el código.
Además, no recibo una warning C4127
para código como este:
void foo(unsigned bar)
{
while (bar >= 0)
;
}
Mi pregunta es: ¿No está la warning C4127: conditional expression is constant
completamente inútil y no motiva el código feo? ¿Alguna vez esta advertencia ayuda a escribir mejor código?
Una advertencia de que una expresión condicional es constante puede ser útil. En muchos casos, puede apuntar a un error lógico en su código.
Por ejemplo, si escribes algo como:
if (x != NULL) { /* ... */ }
donde x
es un objeto de matriz, la expresión es válida, pero la expresión x
decae en un puntero al elemento inicial de la matriz, que no puede ser un puntero nulo. No sé si eso produce el mismo error, pero es un ejemplo del mismo tipo de cosas.
Por supuesto que no siempre es útil. En tu caso, la
do { /* ... */ } while (0)
idioma es la mejor manera de escribir una definición de macro que está diseñada para usarse en un contexto que requiere una declaración. Es probable que el uso de while (0)
en otro contexto sea un error lógico [*].
Es desafortunado que su compilador no lo reconozca como un idioma común. Generar buenas advertencias es complicado; El compilador debe ir más allá de las reglas del lenguaje e inferir la intención del programador.
En este caso, el uso de algún método específico del compilador para suprimir la advertencia (siempre que no rompa el código de otros compiladores) es probablemente el mejor enfoque. Usar una opción de línea de comando para suprimir la advertencia en todos los casos sería excesivo; podría pasar por alto advertencias válidas en otras partes de su código.
Aparentemente, escribir while (0,0)
lugar de while (0)
evita la advertencia. Si lo hace, debe agregar un comentario que indique claramente que es una solución para su compilador en particular. No hay ninguna razón particular por la que un compilador no deba advertir sobre while (0,0)
o cualquier otro código equivalente.
[*] Puede tener sentido escribir una instrucción do { /* ... */ } while (0)
si quieres poder usar break
para saltar fuera de ella.