Macros de preprocesador de varias líneas

81

¿Cómo hacer una macro de preprocesador de varias líneas? Sé cómo hacer una línea:

#define sqr(X) (X*X)

pero necesito algo como esto:

#define someMacro(X)
    class X : public otherClass
    {
         int foo;
         void doFoo();
    };

¿Cómo puedo hacer que esto funcione?

Este es solo un ejemplo, la macro real puede ser muy larga.

gato ruidoso
fuente
Puede obtener fácilmente la respuesta buscando el SO. por ejemplo, stackoverflow.com/questions/4007865/…
Forever Learner
diferentes métodos están aquí: parashift.com/c++-faq/macros-with-multi-stmts.html
Ayrat
Relacionado: stackoverflow.com/questions/98944/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

123

Se utiliza \como carácter de escape de continuación de línea.

#define swap(a, b) {               \
                       (a) ^= (b); \
                       (b) ^= (a); \
                       (a) ^= (b); \
                   }

EDITAR: Como @abelenky señaló en los comentarios, el \carácter debe ser el último carácter de la línea . Si no es así (incluso si es solo un espacio en blanco después), obtendrá mensajes de error confusos en cada línea posterior.

Ed S.
fuente
44
Una advertencia: asegúrese de que \ sea el último carácter de la línea. En C, el espacio en blanco normalmente no importa, pero en este caso, el espacio en blanco invisible al final de la línea puede matarte.
abelenky
2
Sin embargo, se debe agregar que el texto resultante está en una línea. Debido a que C trata todos los espacios en blanco entre tokens de la misma manera, generalmente no importa mucho, pero aún así.
Peter - Reincorpora a Monica
Otra cosa que sugeriría hacer es colocar ` after all useful lines of the macro, and add a comment afterward saying something like // Línea en blanco requerida después de la macro . It's sometimes easier to ensure that all lines of a macro end with `que para asegurarse de que todas las líneas menos la última lo hagan .
supercat
No sabía que podía usar el xor bit a bit de esa manera para intercambiar variables, ¡pero desearía haberlo tenido!
cmarangu
18

Puede hacer que una macro abarque varias líneas colocando una barra invertida ( \) al final de cada línea:

#define F(x) (x)   \
              *    \
             (x)
Kerrek SB
fuente
18

TENGA EN CUENTA que como señalaron Kerrek SB y coaddict, que debería haber sido señalado en la respuesta aceptada, SIEMPRE coloque llaves alrededor de sus argumentos. El ejemplo sqr es el ejemplo simple que se enseña en los cursos de CompSci.

Aquí está el problema: si lo define de la forma en que lo hizo, ¿qué sucede cuando dice "sqr (1 + 5)"? Obtienes "1 + 5 * 1 + 5" o 11.
Si colocas correctamente los tirantes, #define sqr(x) ((x)*(x))
obtienes ((1 + 5) * (1 + 5)) o lo que queríamos 36 ... hermoso.

Ed S. va a tener el mismo problema con 'swap'

jiveturkey
fuente
¿qué tal sqr(++i)? (supongamos que tenemos un int i) :)
Géza Török
Lo hice como ejercicio y aparentemente ise incrementa a medida que se sustituye en la macro (en este caso se sustituye dos veces), luego se multiplica. Así quesqr(++5) == ((7) * (7))
jiveturkey
2
@ GézaTörök La expansión de sqr(++i)to ((++i)*(++i))invocaría un comportamiento indefinido porque el valor de ise modifica más de una vez dentro de esa declaración (sin punto de secuencia entre las operaciones).
moooeeeep
5

Debe escapar de la nueva línea al final de la línea escapándose con un \:

#define sqr(X) \
        ((X)*(X))
codaddict
fuente