tres tipos son programa preprocesamiento preprocesador los lenguaje funcion estructura ejemplos directivas directiva datos constantes básicos c++ visual-c++ c++11 c-preprocessor compiler-bug

programa - los tres tipos de datos básicos en lenguaje c++ son



¿Qué tiene de especial R y L en el preprocesador C++? (2)

Esto parece ser un error en el preprocesador MSVC. La buena noticia es que, dependiendo de lo delicado que sea con su salida, puede solucionar el problema colocando un espacio después de la R o L.

A(L ?p:q), // "L ?p:q"

Ejecuté el siguiente código a través del preprocesador de Visual Studio 2013. La salida me sorprende.

Contenido de hello.cpp:

#define A(j) #j A(A?) A(B?) A(C?) A(D?) A(E?) A(F?) A(G?) A(H?) A(I?) A(J?) A(K?) A(L?) A(M?) A(N?) A(O?) A(P?) A(Q?) A(R?) A(S?) A(T?) A(U?) A(V?) A(W?) A(X?) A(Y?) A(Z?)

El comando:

cl /P hello.cpp

hello.i contiene:

#line 1 "hello.cpp" "A?" "B?" "C?" "D?" "E?" "F?" "G?" "H?" "I?" "J?" "K?" "L" "M?" "N?" "O?" "P?" "Q?" "R" "S?" "T?" "U?" "V?" "W?" "X?" "Y?" "Z?"

Me encontré con esto al tratar de llamar a A (L? P: q), lo que resultó en "Lp: q", que no es bueno para mí.

¿Es este C ++ correcto y bien definido? ¿Qué tiene de especial L y R en C ++? Si el archivo tiene la extensión .c, L y R se tratan de manera idéntica al resto del alfabeto. ¿Esto está relacionado con C ++ 11? Debe ser una característica nueva, ya que las versiones anteriores de MSVS no pisa L y R de una manera especial.

¿Y qué puedo hacer para evitar que MSVS 2013 trate a L y R de esta manera especial?


Actualizar

Parece que el informe de error fue marcado como un duplicado de este que tiene una actualización que dice:

Se ha verificado una solución para este problema en las fuentes del compilador. La corrección debería aparecer en la próxima versión principal de Visual C ++.

Original

Como señaló Remyabel, este es un reported . Ni gcc ni clang producen estos resultados y el operador de stringing # de acuerdo con los documentos de Visual Studios , estos son los siguientes reemplazos (el énfasis es mío en el futuro ):

Se ignora el espacio en blanco que precede al primer token del argumento real y luego del último token del argumento real. Cualquier espacio en blanco entre los tokens en el argumento real se reduce a un único espacio en blanco en el literal de cadena resultante. Por lo tanto, si se produce un comentario entre dos tokens en el argumento real, se reduce a un solo espacio en blanco. El literal de cadena resultante se concatena automáticamente con cualquier literal de cadena adyacente del que solo está separado por espacios en blanco.

Además, si un carácter contenido en el argumento generalmente requiere una secuencia de escape cuando se usa en un literal de cadena (por ejemplo, el carácter de comillas (") o barra invertida ()), la barra invertida de escape necesaria se inserta automáticamente antes del carácter.

que corresponde con el borrador de la sección estándar de C ++ 16.3.2 El operador # que dice:

Si, en la lista de reemplazo, un parámetro está precedido inmediatamente por un token de preprocesamiento #, ambos se sustituyen por un token de preproceso literal de cadena de caracteres único que contiene la ortografía de la secuencia de token de preprocesamiento para el argumento correspondiente. Cada aparición de espacio en blanco entre los tokens de preprocesamiento del argumento se convierte en un único carácter de espacio en el literal de cadena de caracteres. Se elimina el espacio en blanco antes del primer token de preprocesamiento y después de que el último token de preprocesamiento que comprende el argumento. De lo contrario, la ortografía original de cada token de preprocesamiento en el argumento se conserva en el literal de cadena de caracteres, excepto en el manejo especial para producir la ortografía de literales de cadena y literales de caracteres: se inserta un carácter / antes de cada carácter "y" de un carácter literal o cadena literal (incluidos los "caracteres" delimitadores).

Lo único que relaciona a R y L con respecto a C ++ 11 es que tienen un significado especial con los literales de cadena, pero no veo cómo debería afectar este caso.

También parece que L/ y R/ también producen el mismo problema.

Sí documentan un problema no conforme y dice:

Visual C ++ no se comporta correctamente cuando el operador # (stringize) se utiliza con cadenas que incluyen secuencias de escape. En esta situación, el compilador generará el error de compilación C2017.

que no cubre este caso.