¿Cuál es el rol de la directiva #define
?¿Cuál es el propósito de la directiva #define en C++?
Respuesta
#define
se utiliza para crear macros en C y en C++. Puede leer más sobre esto en el C preprocessor documentation. La respuesta rápida es que hace algunas cosas:
Macros simples: basta con solo reemplazar el texto. Tiempo de compilación constantes son un buen ejemplo:
#define SOME_CONSTANT 12
simplemente reemplaza el texto
SOME_CONSTANT
con12
siempre que aparece en el código. Este tipo de macro se usa a menudo para proporcionar una compilación condicional de bloques de código. Por ejemplo, podría haber una cabecera incluida por cada archivo fuente en un proyecto con una lista de opciones para el proyecto:#define OPTION_1 #define OPTION_2 #undef OPTION_3
Y luego los bloques de código en el proyecto se envuelven con juego
#ifdef
/#endif#
bloques para permitir y deshabilitar esas opciones en el proyecto terminado. Usar el indicador-D
gcc proporcionaría un comportamiento similar. Sin embargo, existen fuertes opiniones sobre si este método es realmente una buena forma de proporcionar una configuración para una aplicación.Macros con argumentos: le permite crear macros 'funcionales' que pueden tomar argumentos y manipularlos. Por ejemplo:
#define SQUARE(x) ((x) * (x))
devolvería el cuadrado del argumento como resultado; ¡tenga cuidado con posibles órdenes de operaciones o problemas de efectos secundarios! En el siguiente ejemplo:
int x = SQUARE(3); // becomes int x = ((3) * (3));
voluntad funciona bien, pero algo como:
int y = SQUARE(f()); // becomes int y = ((f()) * (f()));
llamarán
f()
dos veces, o lo que es peor:int z = SQUARE(x++); // becomes int z = ((x++) * (x++));
resulta en un comportamiento indefinido!
Con algunas herramientas, las macros con argumentos también pueden ser variadic, que pueden ser útiles.
Como se menciona a continuación en los comentarios, el uso excesivo de macros, o el desarrollo de macros excesivamente complicadas o confusas se considera mal estilo por muchos - como siempre, puso la legibilidad, mantenibilidad, y debuggability de su código de arriba " hábiles trucos técnicos.
+1. Y dado que OP preguntó acerca del "papel" que desempeña '# define', debe enfatizarse que las macros no deben ser usadas en exceso. – stakx
Las macros variables son estándar en C99, por lo que la mayoría de las herramientas modernas deberían ser compatibles. – pkh
+1, pero debería agregar un ejemplo de cómo SQUARE() será * expandido * en algunas situaciones. – greyfade
#define (y es opuesto, #undef) se puede utilizar para establecer las directivas del compilador que luego se pueden probar contra el uso de #ifndef o #ifdef. Esto permite definir comportamientos personalizados dentro del archivo fuente. Se usa comúnmente para compilar para diferentes entornos o para depurar código.
Un ejemplo:
#define DEBUG
#ifdef DEBUG
//perform debug code
#endif
en C o C++ #define le permite crear macros del preprocesador.
En la normalidad C o C++ proceso de construcción de la primera cosa que sucede es que el preprocesador se ejecuta, el preprocesador se ve sin embargo la fuente de los archivos de directivas de preprocesador #define como o # include y luego se lleva a cabo operaciones simples con ellos.
En el caso de una directiva #define, el preprocesador realiza una simple sustitución basada en texto.
Por ejemplo, si tiene el código
#define PI 3.14159f
float circum = diameter*PI;
el preprocesador lo convertiría en:
float circum = diameter* 3.14159;
simplemente reemplazando los casos de PI con el texto correspondiente. Esta es sólo la forma más simple de una declaración #define para usos más avanzados echa un vistazo a este article de MSDN
inCorrectUseOfHashDefine()
{
El papel de #define es desconcertar a las personas que heredan con su código de las declaraciones azul como:
foreverandever
debido a:
#define foreverandever for(;;)
}
favor favorecer constantes de más de # define.
También para establecer las directivas del compilador ...
¿Por qué el -2? Es un punto válido y me atengo a él. –
porque este * no * es el papel de un #define, sino un * uso indebido * del mismo. –
@Rene OK - He hecho mis intenciones más explícitas –
La directiva #define tiene dos usos comunes.
El primero es controlar cómo actuará el compilador. Para hacer esto, también necesitamos #undef, #ifdef y #ifndef. (y #endif también ...)
Puede hacer "lógica de compilación" de esta manera. Un uso común es para activar o no una porción de depuración del código, al igual que:
#ifdef DEBUG
//debug code here
#endif
y que sería capaz de, por ejemplo, compilar el código de depuración, escribiendo una DEBUG #define
Otro uso de estas cosas lógicas, es evitar el doble incluye ...
Ejemplo, el archivo A, # incluye el archivo B y C. Pero el archivo B también incluye C.Esto probablemente dará como resultado un error de compilación, porque "C" existe dos veces.
La solución es escribir:
#ifndef C_FILE_INCLUDED
#define C_FILE_INCLUDED
//the contents of header "c" go here.
#endif
El otro uso de #define, es hacer que las macros.
Los más simples, consisten en sustituciones simples, como:
#define PI 3.14159265
float perimeter(float radius) {
return radius*2*PI;
}
o
#define SHOW_ERROR_MESSAGE printf("An serious error happened");
if (1 != 1) { SHOW_ERROR_MESSAGE }
, entonces también puede hacer que las macros que aceptan argumentos, printf sí generalmente es una macro, creada con a #define en un archivo de encabezado.
Pero esto no se debe hacer, por dos razones: primero, la velocidad os macros, es lo mismo que usar en línea, y segundo, tenemos plantillas C++, que permiten un mayor control sobre las funciones con tipo de variable. Por lo tanto, la única razón para utilizar macros con argumentos, es hacer construcciones extrañas, que serán difíciles de comprender más tarde, como la materia metaprogrammed ...
Guau, tardé una eternidad en escribir mi publicación, ahora parece que acabo de copiar las publicaciones de dos tipos anteriores y las hice trizas en una :( – speeder
El uso más común (por el momento ) de #define
es para incluir guardias :
// header.hh
#ifndef HEADER_HH_
#define HEADER_HH_
namespace pony {
// ...
}
#endif
Otro uso común de #define
es en la creación de un archivo de configuración, normalmente un archivo config.h, donde #define
macros basa en diversos estados y condiciones. Luego, en nuestro código, probamos estas macros con #ifdef
, #elif defined()
etc. para admitir diferentes compilaciones para diferentes situaciones. Esto no es tan sólido como el modismo de incluir-guardia y debe tener cuidado aquí, porque si la bifurcación es incorrecta, entonces puede obtener errores de compilador muy oscuros, o peor, el comportamiento del tiempo de ejecución.
En general, excepto para incluir guardias que hay que pensar a (dos veces, preferentemente) sobre el problema, y ver si se puede usar el compilador más que el preprocesador para resolverlo. El compilador es simplemente más inteligente que el preprocesador. No solo eso, sino que el compilador posiblemente no puede confundir al preprocesador, mientras que el preprocesador definitivamente puede confundir y engañar al compilador.
La mayoría de cosas sobre #defines han dicho ya, pero no es claro que C++ tiene mejores reemplazos para la mayoría de sus usos:
- #define para definir constantes numéricas pueden ser reemplazados fácilmente por una variable const" ", que, como #define, no existe realmente en el ejecutable compilado. AFAIK se puede usar en casi todas las situaciones en las que podría usar una constante numérica # definida, incluidos los límites de la matriz. La principal ventaja para mí es que tales constantes están claramente tipadas, por lo que no es necesario agregar conversiones en las macros "solo para estar seguro", y tienen un alcance, para que puedan mantenerse en espacios de nombres/clases/funciones, sin contaminar todo solicitud.
const int max_array_size=50;
int an_array[max_array_size];
- #define para crear macros: las macros a menudo pueden ser sustituidas por las plantillas; por ejemplo, la temida MAX macro
#define MAX(a,b) ((a)<(b)?(b):(a))
, que tiene varias desventajas (por ejemplo, repetida evaluación argumentos, la expansión en línea inevitable), puede ser sustituida por la función max
template<typename T> T & max(T & a, T & b)
{
return a<b?b:a;
}
que puede ser seguro (en esta versión, los dos argumentos están forzados a ser del mismo tipo), se puede expandir tanto en línea como no (es decisión del compilador), evalúa los argumentos solo una vez (cuando se llama) y tiene un alcance. Se puede encontrar una explicación más detallada here.
Aún así, todavía macros deben ser usados para incluir guardias, para crear algún tipo de extensiones de lenguaje extraños que se expanden a más línea de código, que tienen paréntesis desequilibrada, etc.
En C++, #define tiene muy estrecho , funciones especializadas: guardias
- de cabecera, que se describen en otras respuestas
- Interactuar con las bibliotecas estándar. Por ejemplo, #definir WINDOWS_LEAN_AND_MEAN antes de incluir windows.h desactiva ciertas macros problemáticas como MAX.
- Macros avanzadas que implican la formación de cadenas (es decir, macros que imprimen mensajes de depuración) o pegado de fichas.
Debe evitar usando #define para los siguientes propósitos. Las razones son muchas; ver para el instance this FAQ entry.
- Constantes de tiempo de compilación. Use
const
en su lugar. - Funciones de macro simples. Use las funciones y plantillas
inline
en su lugar.
- 1. ¿Cuál es el propósito de :: en C#?
- 2. ¿Cuál es el significado de la directiva {$ C PRELOAD}?
- 3. ¿Cuál es el propósito de precompiledApp.config?
- 4. ¿Cuál es el significado de #define en el objetivo C?
- 5. ¿Cuál es el propósito de imbuir en C++?
- 6. ¿Cuál es el propósito de "Container c = getContentPane();" en Swing?
- 7. ¿Cuál es el propósito de typedefing una clase en C++?
- 8. ¿Cuál es el propósito de esta palabra clave en C#
- 9. ¿Cuál es el propósito de los Atributos en C#?
- 10. ¿Cuál es el propósito de la tilde en esta situación?
- 11. ¿Cuál es el propósito de __cxa_pure_virtual?
- 12. ¿Cuál es el propósito de Decimal.One, Decimal.Zero, Decimal.MinusOne en .Net
- 13. ¿Cuál es el propósito de 'var'?
- 14. ¿Cómo se define la directiva __cplusplus en varios compiladores?
- 15. ¿Cuál es el propósito del archivo vshost.exe?
- 16. ¿Cuál es el propósito de estos #define dentro de una enumeración?
- 17. directiva Objective-C#define demonized for String constants
- 18. ¿Cuál es el propósito de 'Class.forName ("MY_JDBC_DRIVER")'?
- 19. ¿Cuál es el propósito de `qt_noop`
- 20. ¿Cuál es el propósito de layout.xml?
- 21. ¿Cuál es el propósito de requestWindowFeature()?
- 22. ¿Cuál es el propósito de la finalización en Java?
- 23. ¿Cuál es el propósito de la serialización en Java?
- 24. ¿Cuál es el propósito de la bandera AI_V4MAPPED en getaddrinfo?
- 25. ¿Cuál es el propósito de la propiedad "privada" en package.json?
- 26. ¿Cuál es el propósito de la clase NullObject en Groovy?
- 27. ¿Cuál es el propósito de la estructura flags en iOS?
- 28. ¿Cuál es el propósito de la clase TestExecution en MSTest?
- 29. ¿Cuál es el propósito de config.assets.precompile?
- 30. ¿Cuál es el propósito de String.IsInterned?
Consulte el código de ejemplo del siguiente artículo como un ejemplo de cómo * no * usar macros: http://stackoverflow.com/questions/2777774/a-out-termniated-garbage-output-due- to-smashing-of-stack-how-to-remove-this –
@Nathan: Vayamos a la verdadera fuente SO de macros malas: http://stackoverflow.com/questions/652788/what-is-the-worst- mundo real-macros-pre-procesador-abuso-youve-ever-across. –
Touche, @David, simplemente fui al más cercano que tenía en la memoria. Su enlace incluye una serie de atrocidades. –