Sustitución mediante macros de texto
El preprocesador permite la sustitución con macros de texto. También se permite macros en forma de función, con parámetros.
Contenido |
[editar]Sintaxis
#define identificadorcontenido-de-sustitución(opcional) | (1) | ||||||||
#define identificador( parámetros) contenido-de-sustitución(opcional) | (2) | ||||||||
#define identificador( parámetros, …) contenido-de-sustitución(opcional) | (3) | (desde C++11) | |||||||
#define identificador(...) contenido-de-sustitución(opcional) | (4) | (desde C++11) | |||||||
#undef identificador | (5) | ||||||||
[editar]Explicación
[editar]Directivas #define
La directiva #define
establece un identificador como macro, es decir, le indica al compilador que sustituya todas las apariciones sucesivas de identificador por el contenido-de-sustitución, que puede estar a su vez procesada adicionalmente. Si el identificador ya está definido como cualquier tipo de macro, el programa es erróneo, está mal formado, a menos que las definiciones sean idénticas.
[editar]Macros como objetos
Una macro de este tipo reemplaza todas las apariciones del identificador definido por el contenido de sustitución. La forma (1) de la directiva #define
se comporta de esta manera.
[editar]Macros con forma de función
Una macro con forma de función reemplaza todas apariciones de el identificador definido por el contenido-de-sustitución, además toma una serie de argumentos, que a continuación reemplazará las ocurrencias de cualquiera de los parámetros en el contenido-de-sustitución.
La sintaxis de invocación de una macro en forma de función es similar a la de llamada a una función: cada instancia del nombre de la macro seguido de un token ( que introduce la secuencia de tokenes que se sustituyen por el contenido-de-sustitución. La secuencia se termina con el token ), omitiendo los pares intermedios coincidentes de paréntesis izquierdo y derecho.
Para la forma (2), el número de argumentos debe ser el mismo que el de parámetros en la definición de la macro. Para las formas (3,4), el número de argumentos no debe ser menor que el de parámetros (no(desde C++20) contando ...
). De lo contrario el programa está mal formado. Si el identificador no está en notación funcional, por ejemplo no tiene paréntesis después de el, no se sustituye nada.
La forma (2) de la directiva #define
determina una macro en forma de función simple.
La forma (3) de la directiva #define
declara una macro en forma función con un número variable de argumentos. A los argumentos adicionales (denominados argumentos variables) se puede acceder utilizando el identificador __VA_ARGS__
, que luego se reemplaza por los argumentos, suministrados con el identificador de la macro.
La forma (4) de la directiva #define
declara una macro de tipo función con un número variable de argumentos, pero sin argumentos normales. Los argumentos (denominados argumentos variables) sólo son accesibles con el identificador __VA_ARGS__
, que luego se reemplaza por los argumentos, suministrados con el identificador de la macro.
Para las formas (3,4), contenido-de-sustitución puede contener la secuencia del token #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) F(a, b, c)// sustituido por f(0, a, b, c) F()// sustituido por f(0) #define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) G(a, b, c)// sustituido por f(0, a, b, c) G(a, )// sustituido por f(0, a) G(a)// sustituido por f(0, a) #define SDEF(snombre, ...) S snombre __VA_OPT__(= { __VA_ARGS__ }) SDEF(foo);// sustituido por S foo; SDEF(bar, 1, 2);// sustituido por S bar = { 1, 2 }; | (desde C++20) |
Nota: si un argumento de una macro en forma de función incluye comas que no están protegidas por un par de paréntesis izquierdo y derecho (muy común en listas de argumentos de plantilla, como assert(std::is_same_v<int, int>); o BOOST_FOREACH(std::pair<int,int> p, m)), la coma se interpreta como un separador de argumentos de macro, que provoca un error de compilación debido a una discrepancia en el número de argumentos.
[editar] Nombre de macro reservados
Un unidad de traducción que incluye una cabecera de biblioteca estándar no puede usar nombres en #define
o #undef
que estén declarados en la cabecera en cualquier cabecera de la biblioteca estándar.
Una unidad de traducción que utiliza cualquier parte de la biblioteca estándar no puede usar nombres en las directivas #define
o #undef
que sean léxicamente idénticas a:
(desde C++11) |
excepto que | (desde C++20) |
De lo contrario, el comportamiento es indefinido.
[editar]Operadores #
y ##
En las macros de tipo función, un operador #
antes de un identificador en el contenido-de-sustitución, procede al reemplazo de parámetros y encierra el resultado entre comillas, creando un literal de cadena. Además, el preprocesador añade barras inversas (\)
para escapar las comillas, si las hay, dentro del literal de cadena, y dobla las barras invertidas (\\)
dentro del literal si es necesario. Se eliminan todos los espacios en blanco iniciales y finales, y cualquier secuencia de espacios en blanco dentro del texto (pero no dentro de las cadenas de texto embebidas) se convierte en un solo espacio. Esta operación se denomina "conversión a cadena". Si el resultado de la “conversión a cadena” no es un literal de cadena válido, el comportamiento es indeterminado.
{{rrev|since=c++11| Cuando #
aparece antes de __VA_ARGS__
, la expansión entera de __VA_ARGS__
se encierra entra comillas:
#define verlista(...) poner(#__VA_ARGS__) verlista();// se expande a poner("") verlista(1, "x", int);// se expande a poner("1, \"x\", int")
Un operador ##
entre dos identificadores sucesivos en el contenido de sustitución ejecuta el reemplazo de parámetros en los dos identificadores (que no son macros expandidas) y luego concatena el resultado. Esta operación se denomina "concatenación" o "pegado de tokenes". Sólo se puede unir tokenes que juntos forman un símbolo válido: identificadores que forman un identificador más largo, los dígitos que forman un número u operadores +
y =
que forman +=
. No se puede crear un comentario uniendo /
y *
porque los comentarios se eliminan del texto antes de la sustitución de macros. Si el resultado comienza con una secuencia que coincide con la sintaxis de un nombre de carácter universal, el comportamiento no está definido. Esta determinación no considera la sustitución de nombres de caracteres universales en la fase 3 de traducción.(desde C++23) Si el resultado de la concatenación no es un token válido, el comportamiento está indefinido.
Nota: algunos compiladores ofrecen una extensión que permite que ##
aparezca después de una coma y antes de __VA_ARGS__
, en cuyo caso, ## no hace nada cuando los argumentos variables están presentes, pero elimina la coma si no hay argumentos variables: esto permite definir macros como fprintf (stderr, format, ##__VA_ARGS__)
.
[editar]Directiva #undef
La directiva #undef
deshabilita el identificador, es decir, se cancela la anterior declaración de la directiva #define
identificador. Si el identificador no estaba declarado como una macro, la directiva se ignora.
[editar]Macros predefinidas
Los nombres de las siguientes macros están predefinidas en cada unidad de traducción.
__cplusplus | indica la versión estándar de C++ en uso, se expande a un valor
|
__STDC_HOSTED__ (C++11) | tiene un valor entero contante 1 si la aplicación está alojada (se ejecuta en un sistema operativo), y 0 si es independiente (funciona sin un sistema operativo). (constante de macro) |
__FILE__ | se sustituye por el nombre del archivo actual, como un literal de cadena de caracteres, puede ser modificado por la directiva #line (constante de macro) |
__LINE__ | se sustituye por el número de línea en el archivo fuente, en forma de constante entera, puede ser modificado por la directiva #line (constante de macro) |
__DATE__ | se sustituye por la fecha de la compilación, como un literal de cadena de caracteres de la forma "Mmm dd yyyy". El primer carácter de "dd" es un espacio si el día del mes es menor de 10. El nombre del mes es como el generado por la función std::asctime() (constante de macro) |
__TIME__ | se sustituye por la hora en que se realizó la compilación, como un literal de cadena de caracteres de la forma "hh:mm:ss". (constante de macro) |
__STDCPP_DEFAULT_NEW_ALIGNMENT__ (C++17) | se expande a un literal std::size_t cuyo valor es la alineación garantizada por una llamada a operador new de alineación sin especificar (se podrán pasar alineamientos más grandes a la sobrecarga de alineamiento especificado, como operator new(std::size_t, std::align_val_t) (constante de macro) |
Los siguientes nombres de macro adicionales pueden estar predefinidas por las implementaciones.
__STDC__ | valor definido por la aplicación. Si está presente, normalmente se usa para indicar que se cumple con la norma de C. (constante de macro) |
__STDC_VERSION__ (C++11) | valor definido por la aplicación. Si está presente indica la versión estándar de C (un entero largo constante de valor aaaammL, donde aaaa es el año y mm el mes). (constante de macro) |
__STDC_ISO_10646__ (C++11) | se expande a una constante entera de la forma aaaammL , si wchar_t utiliza Unicode, la fecha indica la última revisión compatible de Unicode. (constante de macro) |
__STDC_MB_MIGHT_NEQ_WC__ (C++11) | tiene valor 1 si 'x'== L'x' puede ser falso para un miembro del juego de caracteres básico, como en sistemas basados en EBCDIC que usan Unicode para wchar_t. (constante de macro) |
__STDCPP_STRICT_POINTER_SAFETY__ (C++11)(eliminado en C++23) | tiene valor 1 si la aplicación tiene valor strict para std::pointer_safety (constante de macro) |
__STDCPP_THREADS__ (C++11) | de valor 1 si el programa puede tener más de un hilo de ejecución (constante de macro) |
Los valores de estos macros (excepto __FILE__
y __LINE__
) permanecen constantes a lo largo de la unidad de traducción. Los intentos por redeclarar o eliminar la definición de estas macros da como resultado un comportamiento indeterminado.
Nota: dentro del cuerpo de cada función, hay una variable local predefinida especial, llamada __func__, que se define como un array de caracteres estático que contiene el nombre de la función en un formato definido por la aplicación. No es una macro de preprocesador, pero se usa junto con | (desde C++11) |
Macros de prueba de características del lenguajeEl estándar define un conjunto de macros de preprocesador que corresponden a características del lenguaje C++ introducidas en C++ 11 o posterior. Esta pensada como una forma simple y portable de detectar la presencia de dichas características. Para más detalles vea prueba de característica. | (desde C++20) |
[editar]Ejemplo
#include <iostream> //hacer un creador de funciones y utilizarlo#define FUNCION(nombre, a) int fun_##nombre() {return a;} FUNCION(abcd, 12); FUNCION(fff, 2); FUNCION(qqq, 23); #undef FUNCION#define FUNCION 34#define SALIDA(a) std::cout << “salida: “ #a << '\n' // Uso de una macro es la definición de una macro posterior#define PALABRA "Hola "#define EXT(...) PALABRA #__VA_ARGS__ int main(){std::cout<<"abcd: "<< fun_abcd()<<'\n';std::cout<<"fff: "<< fun_fff()<<'\n';std::cout<<"qqq: "<< fun_qqq()<<'\n'; std::cout<< FUNCION <<'\n'; SALIDA(mitexto);//no son necesarias comillas std::cout<< EXT(Mundo)<<'\n';std::cout<< EXT(PALABRA Mundo)<<'\n';}
Salida:
abcd: 12 fff: 2 kkk: 23 34 salida mitexto Hola Mundo Hola PALABRA Mundo
[editar]Véase también
Documentación de C para Macros de sustitución de texto |