Uno en un tiempo hay una necesidad de un no-op de la instrucción en C++. Por ejemplo, cuando la aplicación de assert() que está deshabilitada en la no configuración de depuración (véase también esta pregunta):

#ifdef _DEBUG
#define assert(x) if( !x ) { \
                     ThrowExcepion(__FILE__, __LINE__);\
                  } else {\
                     //noop here \
                  }
#else
#define assert(x) //noop here
#endif

Hasta ahora estoy bajo la impresión de que el camino correcto es el uso de (void)0; para un no-op:

(void)0;

sin embargo, tengo la sospecha de que podría desencadenar advertencias en algunos compiladores – algo así como C4555: expression has no effect; expected expression with side-effect Visual C++ advertencia de que no es emitido para este caso en particular, pero se emite cuando no hay reparto a void.

Es universalmente portátil? Hay una manera mejor?

  • Generalmente no es una buena idea tener macros que va a cambiar el comportamiento del programa basada en la DEPURACIÓN y la LIBERACIÓN… podría acabar con los problemas por los que la DEPURACIÓN (fácil trabajar con ellos) construir se comporta correctamente, pero la VERSIÓN de compilación no. Como de un no-op: ; debe hacerlo, (void)0; (la macro no debe contener el ;, que debe estar a la persona que llama a agregar)
  • Rodríguez – dribeas: Sí, lo sé, pero es una práctica generalizada a tener afirmaciones de movilidad en la no-versiones de depuración y yo sólo lo uso como ejemplo.
  • No entiendo por qué es necesario insertar un no-op en un vacío de otra manera bloque else. Si desea rellenar más tarde, usted puede dejar el bloque else vacío.
  • él es más-para hablar acerca de #define assert(x) //noop here
  • Su primera macro podría estar mejor escrito como #define assert(x) if(x); else ThrowException(__FILE__, __LINE__), que requerirá el punto y coma para compilar correctamente y de buscar/act como una declaración. Dejando en los soportes permiten que se omite, lo que puede ser un problema (sobre todo si su liberación definición de macro requiere que el punto y coma, y se olvidó de usar en algún lugar).
  • si es generalizado o no está relacionado con el hecho de que es un mal lenguaje, si una condición es imposible de alcanzar, y el programa no puede continuar desde allí en la DEPURACIÓN, ¿cómo va a continuar en modo de LANZAMIENTO? En nuestro producto, asserts está habilitado en el modo de disparador, y hemos volcado un pequeño diagnóstico y archivo central, de modo que podemos tratar y diagnosticar lo que salió mal en el campo.
  • Rodríguez – dribeas: ir más lejos -, tenemos dos tipos de afirmaciones. Un tipo siempre está habilitada y se utiliza para la crítica de cheques. El otro está habilitado en las versiones de depuración y sólo se utiliza para diversos paranoico comprueba que sería caro dejar en la no-versiones de depuración.
  • Lutz Que va a causar problemas si usted escribe (¿por qué nunca): if (cond) assert(cond2); – obtendrá un if(cond) ; if(cond2) ; else (....); que es ambiguo. Mejor lugar de todo el asunto en un bloque propio.
  • No es ambigua. El C de la gramática especifica que el else se une con el íntimo if. Parece ambiguo si se agrega incorrecta de la sangría, pero no lo es. (Un compilador lo suficientemente alta configuración de advertencias puede reclamar a ser ambiguo, pero en ese caso la mejor solución es ajustar sus advertencias del compilador para el código que se desea escribir, o el uso do { if(!x) ThrowException(__FILE__, __LINE__); } while(0).)
  • Lutz – estás en lo correcto. No es ambiguo, como correctamente definidos por el C de la gramática, pero usted puede conseguir que el tonto de advertencia y no me gusta advertencias, especialmente no en todo el proyecto utiliza las construcciones. Es por eso que yo prefiero para envolver esas construcciones.

InformationsquelleAutor sharptooth | 2011-11-02

10 Comentarios

  1. 15

    Sospecho que podría desencadenar advertencias en algunos compiladores

    Raro, ya que ((void)0) es lo que la norma assert macro se expande cuando NDEBUG está definido. Por lo que cualquier compilador que emite advertencias para emitirá advertencias siempre que el código que contiene afirma está compilado para la liberación. Espero que pueda ser considerada un error por parte de los usuarios.

    Supongo que un compilador podría evitar ese problema advertencia para su propuesta (void)0 mientras que el tratamiento sólo ((void)0) especialmente. Así que sería mejor usar ((void)0), pero lo dudo.

    En general, algo de calidad a vacío, con o sin el extra que encierra paréntesis, idiomáticamente significa «ignorar esto». Por ejemplo, en el código C que pone en función de los parámetros a void con el fin de suprimir las advertencias para variables sin usar. Así que en ese aspecto, también, un compilador que advirtió que sería bastante impopular, ya que la supresión de una advertencia sólo daría otra.

    Tenga en cuenta que en C++, encabezados estándar permite incluir cada uno de los otros. Por lo tanto, si usted está utilizando cualquier encabezado estándar, assert podría haber sido definidos por que. Por lo tanto el código es no-portátiles en esa cuenta. Si usted está hablando de «universalmente portátil», normalmente se debe tratar cualquier macro definida en cualquier encabezado estándar como reservados identificador. Usted podría undefine, pero con un nombre diferente para su propio afirmaciones sería más sensato. Sé que es sólo un ejemplo, pero no veo por qué te gustaría alguna vez desea definir assert en un «universal portátil», ya que todas las implementaciones de C++ ya la tenemos, y no hacer lo que se está definiendo a hacer aquí.

  2. 17

    El más simple no-op es sólo que no todo el código:

    #define noop

    A continuación, el código de usuario se tiene:

    if (condition) noop; else do_something();

    La alternativa que usted menciona es también un no-op: (void)0;, pero si usted va a utilizar dentro de un macro, debe dejar el ; a un lado de la persona que llama para agregar:

    #define noop (void)0
    if (condition) noop; else do_something();

    (Si ; fue parte de la macro, entonces no sería un extra ; allí)

  3. 8

    ¿ do { } while(0) ? Sí se añade el código, pero estoy seguro de que la mayoría de los compiladores de hoy son capaces de optimizar la basura.

  4. 5

    ; se considera como norma de no-op. Tenga en cuenta que es posible que el compilador no generará ningún código de ella.

    • Bien, las respuestas a la pregunta vinculada sugieren que no es una buena idea.
  5. 1

    Creo que el objetivo aquí, y la razón de no definir la macro para nada, es requieren el usuario para agregar un ;. Para ese propósito, en cualquier lugar de una declaración es legal, (void)0 (o ((void)0), u otras variaciones entonces) está bien.

    Encontré esta pregunta, porque necesitaba hacer la misma cosa en global ámbito, donde un viejo y simple declaración es ilegal. Afortunadamente, C++11 nos da una alternativa: static_assert(true, "NO OP"). Esto puede ser usado en cualquier lugar, y logre mi objetivo de exigir una ; después de la macro. (En mi caso, la macro es una etiqueta para una herramienta de generación de código que se analiza el archivo de origen, por lo que al momento de compilar el código C++, se siempre ser un NO-OP.)

  6. 0

    AFAIK, es universalmente portátil.

    #define MYDEFINE()

    va a hacer así.

    Otra opción puede ser algo como esto:

    void noop(...) {}
    #define MYDEFINE() noop()

    Sin embargo, yo seguiría a (void)0 o el uso de las características intrínsecas como __noop

    • #define assert en su propio código de comportamiento indefinido; la norma dice lo assert debe significar.
    • +1 @JamesKanze no me refiero a literalmente definir afirmar nombre, era un nombre definido por el usuario de marcador de posición. Aclaró.
    • Yo sospechaba como mucho, pero nunca se sabe lo que el lector va a leer en lo que fue para usted una puramente arbitraria elección:-). (El estándar assert generalmente se utiliza (void)0 porque es necesario para ser utilizable como una subexpresión; por ejemplo,someCondition || assert(otherCondition).)
    • Estoy de acuerdo, completamente.
  7. 0
        inline void noop( ) {}

    De auto-documentación de

    • ¿Cómo esta respuesta «Es universalmente portátil? Hay una manera mejor?»
    • En general, evitar el código sólo respuestas. Considerar la adición de un description que ayuda a explicar el código. Creo que se puede hacer mejor que «Auto-documentado». Gracias.
    • Si el lector no entiende lo que hace el código que me sugieren en.cppreference.com o http://www.cplusplus.com. Obviamente portátil si se utiliza un compilador de C++, y si es «mejor» que otra manera es estrictamente la opinión; los lectores pueden utilizar, o no, como quieran.
    • Esto puede causar una llamada a una función y que apenas un «no-op».
    • Que C++ compilador genera código para que a la hora de optimizar?
  8. 0

    este código no se omite la optimización de

    static void nop_func()  {   }
    typedef void (*nop_func_t)();
    static nop_func_t nop = &nop_func;
    
    for (...)
    {
        nop();
    }
    • Es que garantizado?
    • sí, la llamada func a través de la variable puntero no inlineable
    • Es el optimizador prohibido para deducir la función que se llama y en línea de la llamada?
    • Este será optimizado lejos, yo miraba a la salida del compilador, si usted dice estática, en línea o nada en absoluto. Pero usted puede bloquear todas las optimizaciones diciendo vacío nop_func(){asm(«»);}

Dejar respuesta

Please enter your comment!
Please enter your name here