¿Qué significa esta línea? Especialmente, ¿qué significa ##
?¿Qué significa ## en a #define?
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
Editar:
Un poco confundido todavía. ¿Cuál será el resultado sin ##
?
¿Qué significa esta línea? Especialmente, ¿qué significa ##
?¿Qué significa ## en a #define?
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
Editar:
Un poco confundido todavía. ¿Cuál será el resultado sin ##
?
A little bit confused still. What will the result be without ##?
Por lo general, no notará ninguna diferencia.Pero hay es una diferencia. Supongamos que Something
es de tipo:
struct X { int x; };
X Something;
y mirar:
int X::*p = &X::x;
ANALYZE(x, flag)
ANALYZE(*p, flag)
Sin operador de concatenación símbolo ##
, se expande a:
#define ANALYZE(variable, flag) ((Something.variable) & (flag))
((Something. x) & (flag))
((Something. *p) & (flag)) // . and * are not concatenated to one token. syntax error!
con la concatenación señal se expande a:
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
((Something.x) & (flag))
((Something.*p) & (flag)) // .* is a newly generated token, now it works!
Es importante recordar que el preprocesador opera en tokens de preprocesador, , no en texto. Entonces, si desea concatenar dos tokens, debe decirlo explícitamente.
##
se llama concatenación de token, que se utiliza para concatenar dos tokens en una macro invocación.
ver esto:
De hecho, se llama concatenación de token. ¡No creo que la documentación para el compilador IBM AIX C/C++ sea la mejor referencia! –
@David: Agregué esto a mi respuesta. Gracias :-) – Nawaz
@David: No dije IBM AIX C/compilador de C++ es la mejor referencia. La mejor referencia no es otra cosa que el Estándar en sí mismo. Pero damos enlaces a otros sitios de todos modos, incluidos los temas en stackoverflow. – Nawaz
Según Wikipedia
Token concatenation, also called token pasting, is one of the most subtle — and easy to abuse — features of the C macro preprocessor. Two arguments can be 'glued' together using ## preprocessor operator; this allows two tokens to be concatenated in the preprocessed code. This can be used to construct elaborate macros which act like a crude version of C++ templates.
Comprobar Token Concatenation
Una parte muy importante es que esta concatenación símbolo sigue unas reglas muy especiales :
p. Ej. IBM doc:
Ejemplos son también muy auto explicando
#define ArgArg(x, y) x##y
#define ArgText(x) x##TEXT
#define TextArg(x) TEXT##x
#define TextText TEXT##text
#define Jitter 1
#define bug 2
#define Jitterbug 3
Con salida:
ArgArg(lady, bug) "ladybug"
ArgText(con) "conTEXT"
TextArg(book) "TEXTbook"
TextText "TEXTtext"
ArgArg(Jitter, bug) 3
Fuente es la documentación de IBM. Puede variar con otros compiladores.
Para su línea:
Se concatena el atributo variable para el evento "Algo". y hace referencia a una variable que está lógicamente anded, lo que da como resultado si Something.variable tiene un indicador establecido.
Así un ejemplo para mi último comentario y su pregunta (compileable con g ++):
// this one fails with a compiler error
// #define ANALYZE1(variable, flag) ((Something.##variable) & (flag))
// this one will address Something.a (struct)
#define ANALYZE2(variable, flag) ((Something.variable) & (flag))
// this one will be Somethinga (global)
#define ANALYZE3(variable, flag) ((Something##variable) & (flag))
#include <iostream>
using namespace std;
struct something{
int a;
};
int Somethinga = 0;
int main()
{
something Something;
Something.a = 1;
if (ANALYZE2(a,1))
cout << "Something.a is 1" << endl;
if (!ANALYZE3(a,1))
cout << "Somethinga is 0" << endl;
return 1;
};
Vamos a considerar un ejemplo diferente:
considerar
#define MYMACRO(x,y) x##y
sin la ##
, claramente el preprocesador no puede ver x
y y
como señales separadas, ¿verdad?
En su ejemplo,
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
##
simplemente no es necesario, ya que no están haciendo ningún nuevo identificador. De hecho, el compilador emite "error: pegar". "Y" variable "no proporciona un token de preprocesamiento válido"
Esta no es una respuesta a su pregunta, solo una publicación de CW con algunos consejos para ayudarlo a explorar el preprocesador tú mismo.
El paso de preprocesamiento se realiza realmente antes de que se compile cualquier código real. En otras palabras, cuando el compilador comienza a construir su código, no quedan declaraciones #define ni nada por el estilo.
Una buena forma de entender qué hace el preprocesador con su código es obtener la salida preprocesada y observarla.
Se trata de cómo hacerlo para Windows:
Crear un archivo simple llamado test.cpp y la puso en una carpeta, por ejemplo c: \ temp. mina se parece a esto:
#define dog_suffix(variable_name) variable_name##dog
int main()
{
int dog_suffix(my_int) = 0;
char dog_suffix(my_char) = 'a';
return 0;
}
No es muy útil, pero simple. Abra el símbolo del sistema de Visual Studio, vaya a la carpeta y ejecutar el siguiente orden:
c:\temp>cl test.cpp /P
lo tanto, es el compilador de su carrera (cl.exe), con su archivo, y la opción/P indica al compilador que almacena la salida preprocesada a un archivo.
Ahora en la carpeta al lado de test.cpp encontrará la prueba.i, que para mí es el siguiente:
#line 1 "test.cpp"
int main()
{
int my_intdog = 0;
char my_chardog = 'a';
return 0;
}
Como se puede ver, hay #define izquierda, sólo el código que se expandió en.
también ver: http://stackoverflow.com/questions/1597007/creating-c-macro-with-and-line-token-concatenation-with-positioning-macro – sharkin