preprocesamiento - que es el lenguaje preprocesado
¿Por qué usar macros en c? (11)
Posible duplicado:
¿Para qué sirven las macros C?
Cada pocos meses me da ganas de aprender algo de C que mi educación universitaria de programación de mierda nunca cubrió. Hoy son las macros. Mi comprensión básica de las macros es que son una simple búsqueda y reemplazo que ocurre en su código antes de ser compilado. Me cuesta entender por qué usas macros. La mayoría de los ejemplos básicos que estoy viendo son algo así como
TEST(a,%d);
#define TEST(a,b) printf(" The value of " #a " = " #b " /n", a)
//which expands to
printf(" The value of a = %d /n",a);
(ejemplo desde here )
Desde mi punto de vista de novato, parece que definir una nueva función le dará los mismos resultados. Puedo ver cómo las macros históricamente serían útiles para modificar muchas fuentes rápidamente en los días previos a la búsqueda y reemplazo fáciles, pero algo me dice que me estoy perdiendo un punto más importante.
Entonces, ¿qué tipo de cosas útiles pueden hacer las macros por ti?
A veces desea hacer el registro, pero solo en el modo de depuración. Entonces escribes algo como:
#ifdef DEBUG
#define LOG_MSG(x) printf(x);
#else
#define LOG_MSG(X)
#endif
A veces, solo desea activar o desactivar algo en función de un interruptor de compilación. Por ejemplo, mi empresa hace una marca conjunta de nuestro producto y los socios piden que se apague. Así que haremos algo como:
#ifndef SPECIAL_PARTNER_BUILD
DoSomethingReallyAwesome();
#endif
Luego compile con -DSPECIAL_PARTNER_BUILD cuando le dé a su compañero las gotas.
Entre muchas otras posibles razones.
A veces, solo quieres guardar la escritura para las cosas que haces una y otra vez. Algunas personas lo toman muy lejos ( tose la tos MFC) y escriben lo que equivale a su propio idioma en Macros para abstraer un API difícil. Esto hace que la depuración de una pesadilla frikkin.
Creo que la mayor ventaja viene cuando se usa como "archivo de configuración"
#define USE_FAST_AGORHITM
//#define USE_SLOW_ONE
Y "constantes" globales
#define MAX_NUMBER_OF_USERS 100000
Hay programas escritos principalmente en macros (verifique, por ejemplo, la implementación AES de Brian Gladman http://www.gladman.me.uk/cryptography_technology/index.php )
El compilador a menudo conoce los detalles de la máquina de destino, por lo que puede usar la compilación condicional para tener una pieza de código para los procesadores big endian y otra para los procesadores little endian. Eso evita que el código esté lleno de código diseñado para un procesador diferente.
Un caso similar es cuando tiene un código de ensamblaje para un sistema en particular, pero un código C para otros sistemas.
En escenarios intensos de rendimiento, puede usar macros para crear un desenrollado de bucle "automático". Los compiladores modernos probablemente hagan un mejor trabajo con esto, pero esa solía ser una aplicación útil para ello.
En las macros, el código de la función se inserta en el flujo de código de la persona que llama. Esto puede, dependiendo de muchas otras cosas, mejorar el rendimiento, porque el optimizador puede integrar el código llamado de manera procesal - optimizar el código llamado en la persona que llama Pero tenga cuidado, porque en las macros no se comprueban los tipos de argumento. Una buena referencia a las funciones en línea (si también está utilizando C ++) y un poco de macros es. http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5
Las macros C pueden generar código en tiempo de compilación. Se puede (ab) utilizar para crear efectivamente lenguajes específicos de dominio con nuevas palabras clave y comportamientos.
Uno de mis ejemplos favoritos es el método de Simon Tatham para implementar coroutines en C a través de macros.
Las macros pueden tener muchos usos diferentes además de funcionar como cosas.
Es muy útil usar macros para cualquier número mágico o cadena relacionada.
#define MY_MAGIC_NUM 57
/*MY_MAGIC_NUM used all through out the code*/
Las macros se expanden en tiempo de compilación. Usted tiene razón al decir que a menudo se abusa de ellos, pero un ejemplo clásico en C sería tener una macro para escribir mensajes de depuración que (cuando se desactiva el modo de depuración en el momento de la compilación) no genera ningún código, por lo que no causa desaceleración.
No es exactamente buscar y reemplazar, es expansión de token. Las macros C son lo que cualquier otro tipo de macro en el mundo de la computación: una forma de escribir algo corto y simple y convertirlo automáticamente en algo más largo y más complicado.
Una de las razones por las que se utilizan las macros es el rendimiento. Son una forma de eliminar la sobrecarga de llamadas de funciones porque siempre se expanden en línea, a diferencia de la palabra clave "en línea", que es una sugerencia que se suele ignorar al compilador y que ni siquiera existía (en el estándar) antes de C99. Por ejemplo, vea la familia de macros FD_ que se usa junto con los fd_sets utilizados por select y pselect. Estos fd_sets son realmente solo bitsets, y las macros FD_ están ocultando operaciones de twiddling de bits. Sería molesto escribir el bit que se mueve a ti mismo cada vez, y una llamada a la función sería una gran cantidad de gastos generales para una operación tan rápida si no estuviera en línea.
Además, las macros pueden hacer algunas cosas que las funciones no pueden. Considere la posibilidad de pegar token. Como el preprocesador se ejecuta antes que el compilador, puede hacer nuevos identificadores para que el compilador los use. Esto puede darle una forma abreviada de crear muchas definiciones similares, por ejemplo,
#define DEF_PAIR_OF(dtype) /
typedef struct pair_of_##dtype { /
dtype first; /
dtype second; /
} pair_of_##dtype##_t
DEF_PAIR_OF(int);
DEF_PAIR_OF(double);
DEF_PAIR_OF(MyStruct);
/* etc */
Otra cosa que puede hacer es que una función no pueda convertir la información en tiempo de compilación en información en tiempo de ejecución:
#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p/n", #v, v)
#else
#define REPORT_PTR_VALUE(v)
#endif
void someFunction(const int* reallyCoolPointer) {
REPORT_PTR_VALUE(reallyCoolPointer);
/* Other code */
}
No hay forma de que una función pueda usar el nombre de su parámetro en su salida como lo hace la macro. Esto también demuestra la compilación de código de depuración para las versiones de lanzamiento.
Una razón es hasta que C99, la palabra clave en línea no era estándar en el lenguaje C. Por lo tanto, las macros le permitieron en línea pequeñas funciones. También de alguna manera funcionan como plantillas, es decir. no tiene que especificar tipos en la definición de macro, por ejemplo:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
Esta macro es compatible con enteros, dobles, flotantes, etc.
Usamos este tipo de macro en nuestro código:
// convenience macros for implementing field setter/getter functions
#ifndef CREATE_GET_SET
#define CREATE_GET_SET(PREFIX, FIELD_NAME,FIELD_DATATYPE) /
protected:/
FIELD_DATATYPE PREFIX ## FIELD_NAME;/
public:/
inline FIELD_DATATYPE get ## _ ## FIELD_NAME(void) const/
{ /
return(PREFIX ## FIELD_NAME); /
} /
inline void set ## _ ## FIELD_NAME(FIELD_DATATYPE p) /
{ /
PREFIX ## FIELD_NAME = p; /
}
#endif
dentro de una clase / estructura definirías una variable:
CREATE_GET_SET(_, id, unsigned int);
Esto definiría su variable y crearía el getter / setter genérico para el código. Solo hace que la generación de códigos sea más clara y consistente para obtener / configurar. Claro, puedes escribirlo todo, pero eso es un montón de código de tipo repetitivo. NOTA: esta es solo una de las dos macros. No los publiqué todos. No manejarías decir "char *" de esta manera (donde quieres que el conjunto extraiga los datos). Esto fue solo una simple demostración de lo que podría hacer con una macro y algunos tipos simples.