Tengo un pequeño problema con un preprocesador que me desconcierta y no puedo encontrar ninguna explicación en la documentación/preprocesador/especificaciones de idioma.
#define booboo() aaa booboo()bbb booboo().bbbes preprocesado en:
aaa bbb <--- why is space added here aaa.bbbDespués de manejar trígrafos, líneas continuas y comentarios, el preprocesador trabaja en las directivas del preprocesador y divide la entrada en tokens de preprocesamiento y espacios en blanco. La lista de reemplazo de booboo comprende un token pp que es el identificador 'aaa'. booboo()bbb se divide en pp-tokens: 'booboo', '(', ')', 'bbb'. La secuencia de 'booboo', '(', ')' se reconoce como una invocación de macro funcional y debe expandirse a 'aaa' y en mi humilde opinión, la salida debería verse como 'aaabbb'. Dije parecer desde que, para los humanos, se vería como un token, mientras que el compilador obtendría 2 tokens 'aaa' y 'bbb' ya que no se usó el operador '##' que permite la concatenación de tokens pp. ¿Por qué/qué regla hace que cpp (preprocesador c) coloque espacio adicional entre 'aaa' y 'bbb' cuando 'booboo().bbb' da como resultado 'aaa.bbb' sin espacio?
¿Esto se debe a que cpp intenta hacer que la salida (que es principalmente para humanos) no sea ambigua? El ser humano no puede decir que 'aaabbb' está compuesto por 2 fichas, ya que solo ve la ortografía de las fichas. ¿Tengo razón? He leído la documentación de C99 sobre el preprocesador y la documentación de gcc para cpp. No veo nada al respecto.
Si tengo razón, tenemos una situación similar aquí:
#define baba() + baba()+ baba()-resultados en:
+ + +-De lo contrario (si '++' es la salida), a un humano le parecería un token '++', pero habría 2 tokens '+' y '+'. ¿Es como con el operador '##' que cpp verifica si la concatenación produce un token válido pero en los casos mostrados quiere evitar que se realice la concatenación humana? '+-' no es ambiguo, por lo tanto, no se agrega espacio
El resultado del preprocesamiento es transformar el archivo fuente en una lista de tokens. En su caso, la lista de tokens se vería así, después de la tokenización:
.... booboo() bbb ....y luego después del reemplazo de macro:
.... aaa bbb ....Luego, el compilador traduce la lista de tokens en un ejecutable.
El espacio en blanco que está viendo es solo un detalle de implementación que su compilador, etc., ha elegido para diseñar los tokens de preprocesamiento cuando le muestra un resultado intermedio. Los estándares no dicen nada sobre ningún archivo de procesamiento intermedio. Tampoco se requiere que haya un programa separado para hacer el preprocesamiento.
Yo mismo escribí un compilador ANSI C a principios de los 90. Por lo que recuerdo, un token de comentario / ...... / debe reemplazarse por un solo espacio en blanco. Las macros reemplazan el texto en su lugar. No es necesario que los tokens que resulten del reemplazo de texto de dichas macroexpansiones sean tokens de lenguaje C legales. Cuando una macro se define como texto 'aaa', es solo ese texto 'aaa' el que se abre paso en el flujo de entrada. ¡El analizador de C puede o no ver tokens válidos como resultado de eso!
Por lo tanto, dado:
Expandir booboo()bbb debería dar como resultado el texto aaabbb
Lo que significa aaabbb depende del usuario. Pero ese aaabbb no será preprocesado incluso si resulta ser el nombre de una macro. Eso es seguro. Pero aaabbb podría ser un identificador de usuario, no hay problema.