que programa preprocesamiento preprocesador lenguaje informatica ifdef funcion estructura ejemplos directivas directiva define c++ c c-preprocessor preprocessor-directive

programa - funcion preprocesador en c++



¿Es posible definir otra directiva preprocesador? (6)

He estado buscando en el código de golf y se me ocurrió una idea para probar este código:

#define D #define después de agregar esta línea, todo funcionó bien, sin embargo, lo amplié a esto:

#define D #define D VALUE

Y aquí tengo 5 errores de compilación. Si cambio D en #define todo está bien, ¿puede alguien explicar por qué este código es ilegal?

NOTA: Utilicé el compilador VS2008.

EDITAR: Después de algunas respuestas veo que necesitaba dar una lista de errores de compilaciones:

  1. error C2121: ''#'': carácter no válido: posiblemente el resultado de una expansión de macro
  2. error C2146: error de sintaxis: falta '';'' antes del identificador ''VALUE''
  3. error C4430: falta el especificador de tipo - se supone que se int. Nota: C ++ no es compatible con default-int
  4. error C2144: error de sintaxis: ''void'' debe ir precedido por '';''
  5. error C4430: falta el especificador de tipo - se supone que se int. Nota: C ++ no es compatible con default-int

El primer error muestra que D no solo define sino que también incluye # .


C 2011 (N1570) 6.10.3.4 3: "La secuencia de token de preprocesamiento completamente reemplazada por macros resultante no se procesa como una directiva de preprocesamiento, incluso si se parece a una, ..."

C ++ 2010 (N3092) 16.3.4 [cpp.rescan] 3 tiene exactamente el mismo texto.


Eso no funcionará porque el preprocesamiento se realiza en una sola pasada. Por ejemplo, considere el siguiente código:

#define MYDEFINEWEIRD #define MYDEFINEWEIRD N 6 int main() { return 0; }

Después de preprocesar, su código se verá así:

#define N 6 int main() { return 0; }

y "#define" no es una sintaxis válida en C o C ++. Además, como la directiva del preprocesador resultante no se procesará, no resolverá las referencias posteriores a la macro "N" en su código.

Solo por diversión, puede llamar al preprocesor dos veces desde la línea de comando usando g ++ / gcc. Considere el siguiente código (define.cpp):

#include <iostream> #define MYDEFINEWEIRD #define MYDEFINEWEIRD N 6 using namespace std; int main() { cout << N << endl; return 0; }

Entonces puedes hacer:

$ g++ -E define.cpp | g++ -o define -x c++ - && ./define

y saldrá:

6


Este código es ilegal porque la especificación del idioma dice que es ilegal. De acuerdo con la especificación del preprocesador C y C ++, el código que construya utilizando el preprocesador nunca se interpretará como otra directiva de preprocesador. En resumen, no puede crear directivas de preprocesador utilizando preprocesador. Período.

(Además, no puede generar comentarios utilizando el preprocesador).


Las líneas de código en los ojos del preprocesador son declaraciones de preprocesador (y, por lo tanto, no se han hecho reemplazos) o sentencias de texto normales (y se han hecho reemplazos). No se puede tener una de las dos, así que una vez que hayas reemplazado ''D'', solo verás si hay más macros para reemplazar. Como no hay ninguno, simplemente deja ''#define'' en el código C ++ tal como está y el compilador de C ++ generará un error cuando lo vea (ya que ''#define'' no es un código de C ++ válido).

Así que muestre mi punto más, este es un código no válido para el preprocesador:

#define D define #D value

Debido a que el preprocesador no hace ningún reemplazo de macro en las declaraciones del preprocesador, y "#D" no es un comando reconocido del preprocesador. Y esto:

#define D #define D value

Resultados en este código C ++:

#define value

Lo cual no es válido porque ya se está ejecutando el preprocesador.


Mirando la gramática en el párrafo 1 de 16 [cpp], una lista de reemplazo consta de tokens pp que pueden incluir la directiva # no-de producción que se describe en el párrafo 2 del mismo párrafo que

Una no directiva no comenzará con ninguno de los nombres de directivas que aparecen en la lista.

Es decir, algo de la forma.

#define NAME # define

pasa a ser ilegal! También tenga en cuenta que el # en este contexto no convierte la siguiente palabra en una cadena: la cita que sigue a un # solo ocurre si el # va seguido inmediatamente por un nombre de parámetro de macro en una macro de estilo de función.


Parece que su preprocesador está haciendo la sustitución que desea, pero es probable que no obtenga el comportamiento que desea: el preprocesador normalmente es solo una operación de un solo paso. Ejemplo (con clang, pero debería poder reproducir usando los indicadores VS2008 apropiados):

$ cat example.c #define D #define D VALUE $ cc -P -E example.c #define VALUE

Ese #define VALUE está yendo directamente al compilador, que no sabrá qué hacer con él, es una directiva de preprocesador, después de todo. El error de Clang, como referencia, es similar al tuyo:

$ cc -c example.c example.c:2:1: error: expected identifier or ''('' D VALUE ^ example.c:1:11: note: expanded from macro ''D'' #define D #define ^ 1 error generated.