Replacing text macros
El preprocesador admite el reemplazo de macros de texto. También se admite el reemplazo de macros de texto similares a funciones.
Contenidos |
Sintaxis
#define
identificador lista-de-reemplazo
(opcional)
|
(1) | ||||||||
#define
identificador
(
parámetros
)
lista-de-reemplazo
(opcional)
|
(2) | ||||||||
#define
identificador
(
parámetros
, ...)
lista-de-reemplazo
(opcional)
|
(3) | (desde C++11) | |||||||
#define
identificador
(...)
lista-de-reemplazo
(opcional)
|
(4) | (desde C++11) | |||||||
#undef
identificador
|
(5) | ||||||||
Explicación
#define directivas
Las directivas #define definen el identifier como macro, es decir, instruyen al compilador para reemplazar la mayoría de las ocurrencias sucesivas de identifier con replacement-list , que será procesado adicionalmente. Las excepciones surgen de las reglas de scanning and replacement . Si el identifier ya está definido como cualquier tipo de macro, el programa está mal formado a menos que las definiciones sean idénticas.
Macros similares a objetos
Las macros similares a objetos reemplazan cada aparición del identificador definido con la lista-de-reemplazo . La versión (1) de la directiva #define se comporta exactamente de esa manera.
Macros similares a funciones
Las macros similares a funciones reemplazan cada aparición del identificador definido con la lista-de-reemplazo , tomando adicionalmente un número de argumentos, que luego reemplazan las apariciones correspondientes de cualquiera de los parámetros en la lista-de-reemplazo .
La sintaxis de una invocación de macro similar a una función es similar a la sintaxis de una llamada a función: cada instancia del nombre de la macro seguida por un ( como el siguiente token de preprocesamiento introduce la secuencia de tokens que es reemplazada por la replacement-list . La secuencia termina con el token coincidente ) , omitiendo pares coincidentes intermedios de paréntesis izquierdos y derechos.
Para la versión (2), el número de argumentos debe ser el mismo que el número de parámetros en la definición de macro. Para las versiones (3,4), el número de argumentos no debe ser menor que el número 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, es decir, no tiene paréntesis después de sí mismo, no se reemplaza en absoluto.
La versión (2) de la directiva #define define una macro simple similar a una función.
La versión (3) de la directiva
#define
define una macro similar a función con número variable de argumentos. Los argumentos adicionales (llamados
argumentos variables
) pueden accederse usando el identificador
__VA_ARGS__
, que luego es reemplazado con los argumentos suministrados junto al identificador a ser reemplazado.
La versión (4) de la directiva
#define
define una macro similar a una función con número variable de argumentos, pero sin argumentos regulares. Los argumentos (llamados
argumentos variables
) solo pueden accederse con el identificador
__VA_ARGS__
, que luego es reemplazado con los argumentos proporcionados junto con el identificador a ser reemplazado.
|
Para las versiones (3,4),
replacement-list
puede contener la secuencia de tokens
#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) #define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) G(a, b, c) // replaced by f(0, a, b, c) G(a, ) // replaced by f(0, a) G(a) // replaced by f(0, a) #define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 }; |
(desde C++20) |
Nota: si un argumento de una macro similar a una función incluye comas que no están protegidas por pares coincidentes de paréntesis izquierdos y derechos (más comúnmente encontradas en listas de argumentos de plantilla, como en assert ( std:: is_same_v < int , int > ) ; o BOOST_FOREACH ( std:: pair < int , int > p, m ) ), la coma se interpreta como separador de argumentos de macro, causando un fallo de compilación debido a discrepancia en el número de argumentos.
Escaneo y Reemplazo
- El escaneo lleva un registro de las macros que reemplazó. Si el escaneo encuentra texto que coincide con dicha macro, lo marca como "a ignorar" (todos los escaneos lo ignorarán). Esto previene la recursión.
- Si el escaneo encuentra una macro tipo función, los argumentos se escanean antes de colocarse dentro de la replacement-list . Excepto que los operadores # y ## toman el argumento sin escanear.
- Después de que una macro fue reemplazada, el texto resultante se escanea.
Nota, es posible definir una macro pseudo recursiva:
#define EMPTY #define SCAN(x) x #define EXAMPLE_() EXAMPLE #define EXAMPLE(n) EXAMPLE_ EMPTY()(n-1) (n) EXAMPLE(5) SCAN(EXAMPLE(5))
Salida:
EXAMPLE_ ()(5 -1) (5) EXAMPLE_ ()(5 -1 -1) (5 -1) (5)
Nombres de macros reservados
Una unidad de traducción que incluye un encabezado de la biblioteca estándar no puede #define o #undef nombres declarados en cualquier encabezado de la biblioteca estándar .
Una unidad de traducción que utiliza cualquier parte de la biblioteca estándar no puede #define o #undef nombres léxicamente idénticos a:
|
(desde C++11) |
De lo contrario, el comportamiento es indefinido.
# y ## operadores
En macros similares a funciones, un operador # antes de un identificador en la replacement-list procesa el identificador mediante reemplazo de parámetros y lo encierra entre comillas, creando efectivamente un literal de cadena. Además, el preprocesador añade barras invertidas para escapar las comillas que rodean los literales de cadena incrustados, si los hay, y duplica las barras invertidas dentro de la cadena según sea necesario. Se eliminan todos los espacios en blanco iniciales y finales, y cualquier secuencia de espacios en blanco en medio del texto (pero no dentro de literales de cadena incrustados) se reduce a un solo espacio. Esta operación se denomina "stringification". Si el resultado de la stringification no es un literal de cadena válido, el comportamiento es indefinido.
|
Cuando
#
aparece antes de
#define showlist(...) puts(#__VA_ARGS__) showlist(); // expands to puts("") showlist(1, "x", int); // expands to puts("1, \"x\", int") |
(desde C++11) |
Un operador
##
entre dos identificadores sucesivos en la
lista-de-reemplazo
ejecuta el reemplazo de parámetros en los dos identificadores (que no se expanden primero como macros) y luego concatena el resultado. Esta operación se denomina "concatenación" o "pegado de tokens". Solo los tokens que forman un token válido juntos pueden pegarse: identificadores que forman un identificador más largo, dígitos que forman un número, u operadores
+
y
=
que forman un
+=
. No se puede crear un comentario pegando
/
y
*
porque los comentarios se eliminan del texto antes de considerar la sustitución de macros. Si el resultado de la concatenación no es un token válido, el comportamiento es 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 cuando los argumentos variables no están presentes: esto hace posible definir macros como
fprintf
(
stderr
, format,
##__VA_ARGS__)
.
Esto también puede lograrse de manera estándar usando
__VA_OPT__
, como en
fprintf
(
stderr
, format __VA_OPT__
(
,
)
__VA_ARGS__
)
.
(desde C++20)
#undef directiva
La directiva #undef anula la definición del identificador , es decir, cancela la definición previa del identificador realizada por la directiva #define . Si el identificador no tiene una macro asociada, la directiva se ignora.
Macros predefinidos
Los siguientes nombres de macros están predefinidos en cada unidad de traducción:
|
__cplusplus
|
denota la versión del estándar C++ que se está utilizando, se expande al valor
|
|
__STDC_HOSTED__
(C++11)
|
se expande a la constante entera
1
si la implementación es hospedada (se ejecuta bajo un SO),
0
si es independiente (se ejecuta sin SO)
(constante macro) |
|
__FILE__
|
se expande al nombre del archivo actual, como un literal de cadena de caracteres, puede ser modificado por la directiva
#line
(constante macro) |
|
__LINE__
|
se expande al número de línea de la
línea física de código fuente
actual, una constante entera, puede ser modificado por la directiva
#line
(constante macro) |
|
__DATE__
|
se expande a la fecha de traducción, 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 que 10. El nombre del mes es como si fuera generado por
std::
asctime
(
)
(constante macro) |
|
__TIME__
|
se expande a la hora de traducción, un literal de cadena de caracteres de la forma
"hh:mm:ss"
(constante 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
operator new
sin conciencia de alineación (las alineaciones mayores se pasarán a la sobrecarga con conciencia de alineación, como
operator new
(
std::
size_t
,
std::
align_val_t
)
)
(constante macro) |
|
__STDCPP_BFLOAT16_T__
__STDCPP_FLOAT16_T__
__STDCPP_FLOAT32_T__
__STDCPP_FLOAT64_T__
__STDCPP_FLOAT128_T__
(C++23)
|
se expande a
1
si y solo si la implementación soporta el correspondiente
tipo de punto flotante extendido
(constante macro) |
|
__STDC_EMBED_NOT_FOUND__
__STDC_EMBED_FOUND__
__STDC_EMBED_EMPTY__
(C++26)
|
se expande a
0
,
1
y
2
respectivamente
(constante macro) |
Los siguientes nombres de macros adicionales pueden estar predefinidos por las implementaciones:
|
__STDC__
|
valor definido por la implementación, si está presente, típicamente utilizado para indicar conformidad con C
(macro constante) |
||||
|
__STDC_VERSION__
(C++11)
|
valor definido por la implementación, si está presente
(macro constante) |
||||
|
__STDC_ISO_10646__
(C++11)
|
(macro constante) |
||||
|
__STDC_MB_MIGHT_NEQ_WC__
(C++11)
|
se expande a
1
si
'x'
==
L
'x'
podría ser falso para un miembro
x
del conjunto de caracteres básico, como en sistemas basados en EBCDIC que utilizan Unicode para
wchar_t
(macro constante) |
||||
|
__STDCPP_THREADS__
(C++11)
|
se expande a
1
si el programa puede tener más de un hilo de ejecución
(macro constante) |
|
__STDCPP_STRICT_POINTER_SAFETY__
(C++11)
(eliminado en C++23)
|
se expande a
1
si la implementación tiene seguridad estricta de punteros
std::pointer_safety
(constante macro) |
Los valores de estas macros (excepto para
__FILE__
y
__LINE__
) permanecen constantes a lo largo de la unidad de traducción. Los intentos de redefinir o anular estas macros resultan en comportamiento indefinido.
Macros de prueba de características del lenguajeEl estándar define un conjunto de macros de preprocesador correspondientes a características del lenguaje C++ introducidas en C++11 o posteriores. Están diseñadas como una forma simple y portable de detectar la presencia de dichas características. Ver Pruebas de características para más detalles. |
(desde C++20) |
NotasLa variable predefinida local a la función __func__ no es una macro predefinida, pero normalmente se utiliza junto con __FILE__ y __LINE__ , por ejemplo por assert . |
(desde C++11) |
Ejemplo
#include <iostream> // Crear fábrica de funciones y usarla #define FUNCTION(name, a) int fun_##name() { return a; } FUNCTION(abcd, 12) FUNCTION(fff, 2) FUNCTION(qqq, 23) #undef FUNCTION #define FUNCTION 34 #define OUTPUT(a) std::cout << "output: " #a << '\n' // Usando una macro en la definición de una macro posterior #define WORD "Hello " #define OUTER(...) WORD #__VA_ARGS__ int main() { std::cout << "abcd: " << fun_abcd() << '\n'; std::cout << "fff: " << fun_fff() << '\n'; std::cout << "qqq: " << fun_qqq() << '\n'; std::cout << FUNCTION << '\n'; OUTPUT(million); //nótese la falta de comillas std::cout << OUTER(World) << '\n'; std::cout << OUTER(WORD World) << '\n'; }
Salida:
abcd: 12 fff: 2 qqq: 23 34 output: million Hello World Hello WORD World
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Se aplica a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 2908 | C++98 |
no estaba claro si
__LINE__
se expande al número de línea
física actual o al número de línea lógica actual |
se expande al número de línea
física actual |
| LWG 294 | C++98 |
una unidad de traducción que incluye un encabezado de la biblioteca estándar podría contener
macros que definen nombres declarados en otros encabezados de la biblioteca estándar |
prohibido |
| P2621R2 | C++23 |
no se permitía que los nombres de caracteres universales
se formaran mediante concatenación de tokens |
permitido |
Véase también
|
Documentación de C++
para
Índice de Símbolos de Macro
|
|
|
Documentación de C
para
Reemplazo de macros de texto
|