what va_args macro define c macros concatenation token

va_args - Creando macro C con## y__LINE__(concatenación de token con macro de posicionamiento)



gcc macros (2)

El problema es que cuando se tiene un reemplazo de macro, el preprocesador solo expandirá las macros recursivamente si ni el operador de stringing # ni el operador de pegado de tokens ## se le aplican. Entonces, debe usar algunas capas adicionales de direccionamiento indirecto, puede usar el operador de pegar fichas con un argumento recursivamente expandido:

#define TOKENPASTE(x, y) x ## y #define TOKENPASTE2(x, y) TOKENPASTE(x, y) #define UNIQUE static void TOKENPASTE2(Unique_, __LINE__)(void) {}

Entonces, __LINE__ se expande al número de línea durante la expansión de UNIQUE (ya que no está involucrado con # o ## ), y luego el pegado del token ocurre durante la expansión de TOKENPASTE .

También se debe tener en cuenta que también existe la macro __COUNTER__ , que se expande a un nuevo entero cada vez que se evalúa, en caso de que necesite tener múltiples instancias de la macro UNIQUE en la misma línea. Nota: __COUNTER__ es compatible con MS Visual Studio, GCC (desde V4.3) y Clang, pero no es estándar C.

Quiero crear una macro C que crea una función con un nombre basado en el número de línea. Pensé que podría hacer algo como (la función real tendría instrucciones dentro de los corchetes):

#define UNIQUE static void Unique_##__LINE__(void) {}

Lo cual esperaba que se expandiera a algo como:

static void Unique_23(void) {}

Eso no funciona. Con la concatenación de tokens, las macros de posicionamiento se tratan literalmente y terminan expandiéndose a:

static void Unique___LINE__(void) {}

¿Es posible hacer esto?

(Sí, hay una razón real por la que quiero hacer esto, no importa cuán inútil parezca).


GCC no requiere "envoltura" (o realización) a menos que el resultado deba ser "codificado". Gcc tiene características, pero TODO se puede hacer con la versión 1 de C simple (y algunos argumentan que Berkeley 4.3 C es mucho más rápido, vale la pena aprender a usarlo).

** Clang (llvm) NO HACE EL ESPACIO BLANCO CORRECTAMENTE para la macroexpansión: agrega espacio en blanco (que ciertamente destruye el resultado como un identificador C para un preprocesamiento posterior) **, clang simplemente no hace # o * macro expansión como se espera un preprocesador C durante décadas. El mejor ejemplo es la compilación de X11, la macro "Concat3" está rota, su resultado es ahora el identificador MISNAMED C, que por supuesto no se puede construir. y estoy comenzando a creer que construir falla es su profesión.

Creo que la respuesta aquí es "nueva C que rompe estándares es mala C", estos hacks siempre eligen (cambiar espacios de nombres) cambian los valores predeterminados sin ninguna razón, pero realmente no "mejoran C" (salvo en su propia opinión: que yo dicen que es un artilugio hecho para explicar por qué se escapan con todas las fracturas que nadie les ha hecho responsables).

No es un problema que los preprocesadores anteriores de C no admitieran UNIq_ () __ porque admitían #pragma que permite que "hackers de la marca del compilador en el código se marquen como hackers" y también funcionan igual de bien SIN afectar los estándares: tan solo cambiando por defecto es inútil la ruptura de wonton, y lo mismo que cambiar lo que hace una función al usar el mismo nombre (cloqueo de espacio de nombres de nombres) es ... malware en mi opinión