Replacing text macros
El preprocesador admite el reemplazo de macros de texto y 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
|
(2) | ||||||||
#define
identificador
(
parámetros
, ... )
lista-de-reemplazo
|
(3) | (desde C99) | |||||||
#define
identificador
( ... )
lista-de-reemplazo
|
(4) | (desde C99) | |||||||
#undef
identificador
|
(5) | ||||||||
Explicación
#define directivas
Las
#define
directivas definen el
identifier
como una macro, es decir, instruyen al compilador para reemplazar todas las ocurrencias sucesivas de
identifier
con
replacement-list
, que puede ser procesado opcionalmente de manera adicional. Si el identificador 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 de tipo objeto reemplazan cada aparición de un
identificador
definido con una
lista-de-reemplazo
. La versión (1) de la directiva
#define
se comporta exactamente de esta manera.
Macros similares a funciones
Las macros similares a funciones reemplazan cada aparición de un identificador definido con una 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 de un ( como el siguiente token de preprocesamiento introduce la secuencia de tokens que es reemplazada por la lista de reemplazo. La secuencia termina con el token ) coincidente, omitiendo los pares coincidentes de paréntesis izquierdo y derecho intermedios.
El número de argumentos debe ser el mismo que el número de argumentos en la definición de la macro ( parameters ) o 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 una función con número variable de argumentos. Los argumentos adicionales pueden accederse usando el identificador
__VA_ARGS__
, que luego es reemplazado con los argumentos proporcionados 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 solo pueden accederse con el identificador
__VA_ARGS__
, que luego es reemplazado con los argumentos proporcionados al 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 C23) |
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 (como
macro
(
array
[
x
=
y, x
+
1
]
)
o
atomic_store
(
p,
(
struct
S
)
{
a, b
}
)
;
), 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.
# y ## operadores
En las macros similares a funciones, un operador
#
antes de un identificador en la
replacement-list
procesa el identificador mediante reemplazo de parámetros y encierra el resultado 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
#define showlist(...) puts(#__VA_ARGS__) showlist(); // expands to puts("") showlist(1, "x", int); // expands to puts("1, \"x\", int") |
(desde C99) |
Un operador
##
entre dos identificadores sucesivos en la
replacement-list
ejecuta el reemplazo de parámetros en los dos identificadores y luego concatena el resultado. Esta operación se denomina "concatenación" o "token pasting". 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 el
##
no hace nada cuando
__VA_ARGS__
no está vacío, pero elimina la coma cuando
__VA_ARGS__
está vacío: esto hace posible definir macros como
fprintf
(
stderr
, format,
##__VA_ARGS__)
.
El orden de evaluación de los operadores
#
y
##
no está especificado.
#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 cualquier unidad de traducción:
|
__STDC__
|
se expande a la constante entera
1
. Esta macro está destinada a indicar una implementación conforme
(constante de macro) |
|
__STDC_VERSION__
(C95)
|
se expande a una constante entera de tipo
long
cuyo valor aumenta con cada versión del estándar C:
|
|
__STDC_HOSTED__
(C99)
|
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 de macro) |
|
__FILE__
|
se expande al nombre del archivo actual, como un literal de cadena de caracteres, puede ser modificado por la directiva
#line
(constante de macro) |
|
__LINE__
|
se expande al número de línea del archivo fuente, una constante entera, puede ser modificado por la directiva
#line
(constante de macro) |
|
__DATE__
|
se expande a la fecha de traducción, un literal de cadena de caracteres de la forma "Mmm dd aaaa". El nombre del mes es como si fuera generado por
asctime
y el primer carácter de "dd" es un espacio si el día del mes es menor que 10
(constante de macro) |
|
__TIME__
|
se expande a la hora de traducción, un literal de cadena de caracteres de la forma "hh:mm:ss", como en la hora generada por
asctime
(
)
(constante de macro) |
|
__STDC_UTF_16__
(C23)
|
se expande a
1
para indicar que
char16_t
utiliza codificación UTF-16
(constante de macro) |
|
__STDC_UTF_32__
(C23)
|
se expande a
1
para indicar que
char32_t
utiliza codificación UTF-32
(constante de macro) |
|
__STDC_EMBED_NOT_FOUND__
__STDC_EMBED_FOUND__
__STDC_EMBED_EMPTY__
(C23)
|
se expanden a
0
,
1
, y
2
, respectivamente
(constante de macro) |
Los siguientes nombres de macros adicionales pueden estar predefinidos por una implementación:
|
__STDC_ISO_10646__
(C99)
|
se expande a una constante entera de la forma
yyyymmL
, si
wchar_t
utiliza Unicode; la fecha indica la revisión más reciente de Unicode compatible
(constante macro) |
|
__STDC_IEC_559__
(C99)
(obsoleto en C23)
|
se expande a
1
si IEC 60559 está soportado
(constante macro) |
|
__STDC_IEC_559_COMPLEX__
(C99)
(obsoleto en C23)
|
se expande a
1
si la aritmética compleja IEC 60559 está soportada
(constante macro) |
|
__STDC_UTF_16__
(C11)
|
se expande a
1
si
char16_t
utiliza codificación UTF-16
(constante macro) |
|
__STDC_UTF_32__
(C11)
|
se expande a
1
si
char32_t
utiliza codificación UTF-32
(constante macro) |
|
__STDC_MB_MIGHT_NEQ_WC__
(C99)
|
se expande a
1
si
'x'
==
L
'x'
podría ser falso para un miembro del conjunto de caracteres básico, como en sistemas basados en EBCDIC que utilizan Unicode para
wchar_t
(constante macro) |
|
__STDC_ANALYZABLE__
(C11)
|
se expande a
1
si el
análisis estático
está soportado
(constante macro) |
|
__STDC_LIB_EXT1__
(C11)
|
se expande a una constante entera
201112L
si las
interfaces de verificación de límites
están soportadas
(constante macro) |
|
__STDC_NO_ATOMICS__
(C11)
|
se expande a
1
si los tipos
atomic
y la
biblioteca de operaciones atómicas
no están soportados
(constante macro) |
|
__STDC_NO_COMPLEX__
(C11)
|
se expande a
1
si
complex types
y
complex math library
no están soportados
(macro constante) |
|
__STDC_NO_THREADS__
(C11)
|
se expande a
1
si
multithreading
no está soportado
(constante macro) |
|
__STDC_NO_VLA__
(C11)
|
se expande a
1
si
los arreglos de longitud variable
y los tipos modificables variables
(hasta C23)
de duración de almacenamiento automático
(desde C23)
no están soportados
(constante macro) |
|
__STDC_IEC_60559_BFP__
(C23)
|
se expande a
202311L
si la aritmética de punto flotante binario IEC 60559 está soportada
(constante macro) |
|
__STDC_IEC_60559_DFP__
(C23)
|
se expande a
202311L
si la aritmética de punto flotante decimal IEC 60559 está soportada
(constante macro) |
|
__STDC_IEC_60559_COMPLEX__
(C23)
|
se expande a
202311L
si la aritmética compleja IEC 60559 está soportada
(constante macro) |
|
__STDC_IEC_60559_TYPES__
(C23)
|
se expande a
202311L
si los tipos extendidos e de intercambio IEC 60559 están soportados
(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.
|
La variable predefinida
__func__
(ver
definición de función
para detalles) no es una macro del preprocesador, aunque a veces se utiliza junto con
|
(desde C99) |
Ejemplo
#include <stdio.h> // make function factory and use it #define FUNCTION(name, a) int fun_##name(int x) { return (a) * x; } FUNCTION(quadruple, 4) FUNCTION(double, 2) #undef FUNCTION #define FUNCTION 34 #define OUTPUT(a) puts( #a ) int main(void) { printf("quadruple(13): %d\n", fun_quadruple(13)); printf("double(21): %d\n", fun_double(21)); printf("%d\n", FUNCTION); OUTPUT(billion); // note the lack of quotes }
Salida:
quadruple(13): 52 double(21): 42 34 billion
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| DR 321 | C99 |
no estaba claro si
L
'x'
==
'x'
siempre se cumple
entre el conjunto de caracteres básico |
__STDC_MB_MIGHT_NEQ_WC__ añadido para este propósito |
Referencias
- Estándar C23 (ISO/IEC 9899:2024):
-
- 6.10.4 Reemplazo de macros (p: 187-184)
-
- 6.10.9 Nombres de macros predefinidos (p: 186-188)
- Estándar C17 (ISO/IEC 9899:2018):
-
- 6.10.3 Reemplazo de macros (p: 121-126)
-
- 6.10.8 Nombres de macros predefinidos (p: 127-129)
- Estándar C11 (ISO/IEC 9899:2011):
-
- 6.10.3 Reemplazo de macros (p: 166-173)
-
- 6.10.8 Nombres de macros predefinidos (p: 175-176)
- Estándar C99 (ISO/IEC 9899:1999):
-
- 6.10.3 Reemplazo de macros (p: 151-158)
-
- 6.10.8 Nombres de macros predefinidos (p: 160-161)
- Estándar C89/C90 (ISO/IEC 9899:1990):
-
- 3.8.3 Reemplazo de macros
-
- 3.8.8 Nombres de macros predefinidos
Véase también
|
Documentación de C++
para
Reemplazo de macros de texto
|