va_args macro define c macros c-preprocessor

define - Extensión cpp de macro sin token-string



define c++ (3)

El preprocesador C opera en "tokens" y siempre que haya una posibilidad de cambiar el significado o la ambigüedad, siempre agrega espacios en blanco para preservar el significado.

Considera tu ejemplo,

(B)

no hay ambigüedad ni significado que altere si hay un espacio entre ( y ) agregado o no, independientemente del valor macro de B

Pero no es el caso con

|B|

Dependiendo de la macro B , esto de arriba podría ser || o |something| . Entonces, el preprocesador se ve obligado a agregar un espacio en blanco para mantener las reglas léxicas de C.

El mismo comportamiento se puede ver con cualquier otro token que pueda alterar el significado. Por ejemplo,

#define B + B+

produciría

+ +

Opuesto a

++

por la mencionada razón.

Sin embargo, este es solo el preprocesador que cumple con las reglas lexicales. GCC tiene y es compatible con un preprocesador antiguo llamado procesador tradicional que no agregaría ningún espacio en blanco adicional. Por ejemplo, si llama al preprocesador en modo tradicional :

gcc -E -traditional-cpp file.c

entonces

#define B (B) |B|

producir (sin el espacio en blanco)

() ||

Estoy leyendo sobre la expansión de macros CPP y quería entender la expansión cuando no se proporciona la cadena token (opcional). Encontré que gcc v4.8.4 hace esto:

$ cat zz.c #define B (B) |B| $ gcc -E zz.c # 1 "zz.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "zz.c" () | |

¿Alguien puede explicar por qué la expansión tiene cero espacios en una instancia y uno en la otra?


La salida de gcc -E intencionalmente no coincide con las reglas exactas especificadas por el estándar C. El estándar C no describe ninguna forma particular en que el resultado del preprocesador debe ser visible, y ni siquiera lo requiere.

La única vez que se requiere que algún tipo de salida de preprocesador sea visible es cuando se utiliza # operador # . Y si usa esto, puede ver que no hay espacio.

La respuesta de flaming.toaster correctamente señala que la razón por la cual la salida gcc -E inserta un espacio es para evitar que los dos | s de ser analizado como un single || simbólico. El siguiente programa es necesario para dar un diagnóstico del error de sintaxis:

#define EMPTY int main() { return 0 |EMPTY| 0; }

y el espacio está ahí para asegurarse de que el compilador todavía tenga suficiente información para generar realmente el error.


editar: vea la respuesta de hvd sobre la implementación del preprocesador de gcc

Esto puede ser para diferenciar entre los operadores OR lógicos a nivel de bit.

Esta muestra:

if (x | 4) printf("true/n"); // Bitwise OR, may or may not be true

Es diferente de:

if (x || 4) printf("true/n"); // Always true

Debido a que son operadores diferentes con funciones diferentes, es necesario que el preprocesador agregue espacios en blanco para evitar cambiar el significado pretendido de la declaración.