He visto depuración printfs en glibc que internamente se define como (void) 0, si NDEBUG está definido. Asimismo, el __noop para el compilador de Visual C++ es demasiado. El primero trabaja en ambos GCC y VC++ compiladores, mientras que el último solo en VC++. Ahora todos sabemos que tanto las declaraciones anteriores, serán tratados como no la operación y no respectivo código será generado; pero aquí es donde tengo la duda.

En caso de __noop, MSDN dice que es una función intrínseca proporcionados por el compilador. Llegando a (void) 0 ~ ¿por Qué es interpretada por los compiladores como no op? Es complicado el uso del lenguaje C o no el estándar de decir algo sobre expresamente? O incluso que es algo que ver con el compilador de implementación?

  • Por sólo dar 0; como una declaración, no entiendo advertencias o errores, y estoy seguro de que no va a hacer cualquier poderosos de la operación y es igual a la de un no op; Incluso si es así, ¿qué tipo de fundición a vacío? Además, en el caso de la #define dbgprintf (void) 0, cuando es llamado como dbgprintf("Hello World!"); -> (void) 0("Hello World!"); – ¿qué significa eso?
  • esto probablemente debería ser #define dbgprintf(x) (void)0; aunque encontré #define dbgprintf(x) perfectamente suficiente. Creo que el elenco de anular es eliminar cualquier tipo de valor de retorno, por lo que si se usan en un contexto que requiere de valor (y no debe), se producirá un error/advertencia, en lugar de pasar en silencio.
  • Sí, no me he dado cuenta de que el #define ignorar param (x) y tan sólo hace un (void) 0. Gracias por señalarla 🙂
  • Bueno, imagínese que usted es un compilador. ¿Qué código se genera de esta declaración:(void) 0;? Ahora que usted sabe.
  • Jaja.. de verdad, me estaba pidiendo más información sobre los detalles en el encasillado, en un idioma laweryese manera 😉
  • ¿Por qué no utilizar #define dbgprintf en lugar de #define dbgprintf ((void) 0) ??? @legends2k hay una razón?
  • La pregunta es más bien centrado en lo que hace ((void) 0) decir. No se cómo definir un no-op macro.
  • Por supuesto sé que. Sólo tenía curiosidad. Para (void)0 necesidades más escribir.

InformationsquelleAutor legends2k | 2010-02-04

5 Comentarios

  1. 62

    (void)0 (+;) es válido, pero ‘no hace nada’ C++ expresión, eso es todo. No se traduce a la no-op de instrucciones de la arquitectura destino, es sólo una declaración vacía como marcador de posición siempre que el idioma espera una declaración completa (por ejemplo, como destino de un salto a la etiqueta, o en el cuerpo de un if cláusula).

    EDICIÓN: (actualizado basado en Chris Lutz comentario)

    Cabe señalar que cuando se utiliza como una macro, decir

    #define noop ((void)0)

    la (void) impide que accidentalmente se utiliza como un valor como

    int x = noop;

    Para la expresión anterior el compilador será, justamente, la bandera es como una operación no válida. GCC escupe error: void value not ignored as it ought to be y VC++ ladra 'void' illegal with all types.

    • Debe tener en cuenta que, utilizado como una macro (es decir, #define noop (void)0), el (void) impide que accidentalmente se utiliza como un valor (como en int x = noop;.
    • Gracias Chris, para aclarar con respecto a por qué la conversión de tipo void se hace; se evita el uso accidental de dicho noop exp. en la expresión como de la asignación, ahora sí entendí.
    • Poner esto como una respuesta :).
    • Yo deseo que yo tenía, excepto que ya he golpeado mi representante de la pac para el día de hoy. La mejor que me podría haber esperado es aceptado la respuesta.
    • Es un poco injusto tengo el ‘aceptado’ ahora – pero al menos tienes una buena cantidad de excelentes comentarios de los votos, incluyendo los míos.
    • Habría tenido mi real upvote, pero se me acabó de votos de varias horas atrás.
    • Se puede incorporar Chris Lutz nota en tu respuesta?
    • Gracias por señalarla, hecho!
    • Gran!………
    • Podemos decir que, es como «pass» en Python?
    • Sí, lo es!
    • Tengo un problema con este (void)(0) de hecho, estoy tratando de hacer (void)(0) += 1 y devolver el valor actualizado que 1. Pero me da 0 como resultado ?

  2. 8

    Cualquier expresión que no tiene ningún tipo de efectos secundarios puede ser tratado como un no-op por el compilador, que dosn no tienen para generar código (aunque se puede). Lo que ocurre es que la fundición y, a continuación, no utilizando el resultado de la fundición es fácil para el compilador (y humanos) a ver como no tener efectos secundarios.

  3. 2

    Creo que estás hablando de glibc, no glib, y la macro en cuestión es el assert macro:

    En glibc <assert.h>, con NDEBUG (sin depuración) definido, assert se define como:

    #ifdef NDEBUG
    #if defined __cplusplus && __GNUC_PREREQ (2,95)
    # define __ASSERT_VOID_CAST static_cast<void>
    #else
    # define __ASSERT_VOID_CAST (void)
    #endif
    # define assert(expr)           (__ASSERT_VOID_CAST (0))
    #else
    /* more code */
    #endif

    que básicamente significa assert(whatever); es equivalente a ((void)(0));, y no hace nada.

    De la C89 estándar (sección 4.2):

    El encabezado <assert.h> define el assert macro y se refiere a otra macro,

    NDEBUG

    que no es definida por <assert.h>. Si NDEBUG se define como un nombre de macro en el punto en el archivo de origen donde <assert.h> está incluido, el assert macro se define simplemente como

    #define assert(ignore) ((void)0)

    No creo que la definición de una impresión de depuración de macros para ser igual a (void)0 hace mucho sentido. Puede que nos muestran dónde se hace eso?

    • Sí, es glibc y no simplista, gracias por notificar; corregido en la pregunta.
    • doc.ddart.net/msdn/header/include/assert.h.html – Este es uno de los muchos assert.hs he visto con (void) 0.
    • no es una impresión de depuración de macros. Mi respuesta anterior responde a su pregunta acerca de assert().
    • Estoy de acuerdo, es la aserción. Pero toda duda era saber más acerca de la (void) 0 en general como de funcionamiento, basado en el lenguaje o el compilador de las construcciones. Gracias!
  4. 1

    Incluso si es así, ¿qué tipo de fundición a vacío? Además, en el caso de la #define dbgprintf (void) 0, cuando es llamado como dbgprintf(«Hola Mundo!»); -> (void) 0(«Hola Mundo!»); – ¿qué significa eso? – legends2k

    Macros reemplazar el código con algo más, así que si usted #define dbgprint (que acepta x) como

    void (0)

    entonces no reescritura de X en sustitución, por lo que dbgprintf(«Holamundo») no serán convertidos a (void) 0(«Hola, mundo»), pero a (void) 0; – no sólo el nombre de la macro dbgprint es reemplazado por (void) 0, pero el conjunto de la llamada dbgprintf(«…»)

    • Sí, yo entiendo que 🙂
  5. 0

    En Windows, yo trate de algún código como este en Main.cpp:

    #include <iostream>
    #define TRACE ((void)0)
    int main() {
      TRACE("joke");
      std::cout << "ok" << std::endl;
      return 0;
    }

    Entonces, voy a construir la versión de archivo exe con el Principal.yo de salida. En Principal.i archivo, el SEGUIMIENTO de la macro fue reemplazado a:((void)0)("joke"), y visual studio dar una advertencia:»advertencia C4353: no estándar de la extensión utilizada: constante de 0 como expresión de función. El uso de ‘__noop función intrínseca en su lugar». Ejecute el archivo exe, consola de imprimir «aceptar» caracteres. Así que creo que todo está claro: la definición de la macro de SEGUIMIENTO[#define TRACE ((void)0)] es ilegal de acuerdo a la sintaxis de c++, pero compilador de c++ de visual studio admite este comportamiento como una extensión de compilador. Así que mi conclusión es: [#define TRACE ((void)0)] es ilegal c++ declaración, y que en el mejor de NO utilizar este. Pero [#define TRACE(x) ((void)0)] es la declaración legal. Eso es todo.

Dejar respuesta

Please enter your comment!
Please enter your name here