Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

Considere esto (, no es bueno muy malo horrible, terrible) estructura de código:

#define foo(x) // commented out debugging code

// Misformatted to not obscure the point
if (a)
foo(a);
bar(a);

He visto preprocesadores dos compiladores generan diferentes resultados en este código:

if (a)
bar(a);

y

if (a)
;
bar(a);

Obviamente, esto es una mala cosa para una base de código portátil.

Mi pregunta: ¿Cuál es el preprocesador supone que ver con esto? Eludir los comentarios en primer lugar, o ampliar las macros primero?

¿Fue útil?

Solución

Desafortunadamente, el href="http://eli-project.sourceforge.net/c_html/c.html" ANSI C Especificación excluye específicamente cualquier característica del preprocesador en la sección de 4 ( "Esta especificación describe sólo el lenguaje C. no hace ninguna provisión para ya sea la biblioteca o el preprocesador.").

La especificación href="http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1124.pdf" rel="noreferrer"> C99 maneja esto de forma explícita , aunque. Los comentarios son sustituidos por un solo espacio en la "fase de traducción", que ocurre antes del análisis directiva de preprocesamiento. (Sección 6.10 para más detalles).

VC ++ y el GNU C Compiler tanto seguir este paradigma - otros compiladores puede no ser compatible si seas mayor, pero si es compatible con C99, usted debe ser seguro.

Otros consejos

Como se describe en esta copia-n-pegado decription de las fases de traducción en el estándar C99, la eliminación de comentarios (que son reemplazados por un solo espacio en blanco) se produce en fase de traducción 3, mientras que las directivas de preprocesamiento se manejan y macros se expanden en la fase 4.

En el estándar C90 (que sólo tengo en copia dura, por lo que no copia-n-pegar) estas dos fases se producen en el mismo orden, aunque la descripción de las fases de traducción es ligeramente diferente en algunos detalles de la norma C99 -. el hecho de que los comentarios son eliminados y reemplazados por un único carácter de espacio en blanco antes del procesamiento previo directivas son manejados y macros ampliada no es diferente

Una vez más, el estándar de C ++ tiene estas 2 fases se producen en el mismo orden.

En cuanto a cómo deben ser manejados los comentarios '' //, el estándar C99 dice esto (6.4.9 / 2):

  

A excepción dentro de una constante de carácter, una cadena literal, o un comentario, los caracteres //   introducir un comentario que incluya todos los caracteres de varios bytes hasta, pero no incluyendo, la   siguiente carácter de nueva línea.

Y el estándar de C ++ dice (2.7):

  

Los caracteres // Iniciar un comentario, que termina con el siguiente salto de línea   personaje.

Así que el primer ejemplo es claramente un error de parte de ese traductor - el carácter ';' después de la foo(a) debe mantenerse cuando se expande la macro foo() - los caracteres de comentario no deberían formar parte de los 'contenidos' de the foo() macro.

Pero ya que se enfrenta a un traductor con errores, es posible que desee cambiar la definición de la macro a:

#define foo(x) /* junk */

para solucionar el error.

Sin embargo (y estoy a la deriva fuera de tema aquí ...), ya que la línea de corte y empalme (barras invertidas justo antes de una nueva línea) se produce antes de que se procesan los comentarios, puede ejecutar en algo como esto poco de código desagradable:

#define evil( x) printf( "hello "); // hi there, \
                 printf( "%s\n", x); // you!



int main( int argc, char** argv)
{
    evil( "bastard");

    return 0;
}

Lo que podría sorprender a todo el que lo escribió.

O mejor aún, trate lo siguiente, escrito por alguien (! Ciertamente no yo) que le gustan los comentarios de estilo caja:

int main( int argc, char** argv)
{
                            //----------------/
    printf( "hello ");      // Hey, what the??/
    printf( "%s\n", "you"); // heck??         /
                            //----------------/
    return 0;
}

En función de si sus valores por defecto del compilador de procesamiento trigrafos o no (compiladores se supone que son, pero desde trigrafos sorpresa casi todos los que se ejecuta a través de ellos, algunos compiladores deciden apagarlos por defecto), que puede o no puede obtener el comportamiento que desea -. sea cual sea el comportamiento que es, por supuesto

De acuerdo con MSDN , los comentarios son reemplazados con un solo espacio en la fase tokenización, lo que sucede antes de la fase de pre-procesamiento, donde se expanden las macros.

Nunca ponga // comentarios en sus macros. Si debe poner comentarios, utilice / * * /. Además, tiene un error en su macro:

#define foo(x) do { } while(0) /* junk */

De esta manera, foo es siempre seguro de usar. Por ejemplo:

if (some condition)
    foo(x);

Nunca arrojará un error del compilador, independientemente de si es o no foo se define en cierta expresión.

#ifdef _TEST_
#define _cerr cerr
#else
#define _cerr / ## / cerr
#endif
  • funcionará en algunos compiladores (VC ++). Cuando _TEST_ no se define,

    _cerr ...

    será reemplazado por la línea de comentario

    // cerr ...

Me parece recordar que el cumplimiento requiere tres pasos:

  1. tira
  2. macros de expansión
  3. tira de nuevo

La razón de esto tiene que ver con el compilador de ser capaz de aceptar .i archivos directamente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top