Diferencia entre Enum y Definir Declaraciones

¿Cuál es la diferencia entre usar una instrucción define y una instrucción enum en C / C ++ (y hay alguna diferencia al usarlas con C o C ++)?

Por ejemplo, cuando debería uno usar

enum {BUFFER = 1234}; 

encima

 #define BUFFER 1234 

enum define un elemento sintáctico.

#define es una directiva de preprocesador, ejecutada antes de que el comstackdor vea el código, y por lo tanto no es un elemento de lenguaje de C en sí mismo.

En general, se prefieren las enumeraciones, ya que son seguras para el tipo y más fácilmente detectables. Las definiciones son más difíciles de localizar y pueden tener un comportamiento complejo, por ejemplo, un código puede redefinir un #define creado por otro. Esto puede ser difícil de rastrear.

#define declaraciones las maneja el preprocesador antes de que el comstackdor vea el código, por lo que básicamente se trata de una sustitución de texto (en realidad es un poco más inteligente con el uso de parámetros y demás).

Las enumeraciones son parte del lenguaje C en sí y tienen las siguientes ventajas.

1 / Pueden tener tipo y el comstackdor puede verificarlos.

2 / Debido a que están disponibles para el comstackdor, la información de símbolos en ellos se puede pasar al depurador, lo que facilita la depuración.

Definir es un comando de preprocesador, es como hacer “reemplazar todo” en su editor, puede reemplazar una cadena por otra y luego comstackr el resultado.

Enum es un caso especial de tipo, por ejemplo, si escribe:

 enum ERROR_TYPES { REGULAR_ERR =1, OK =0 } 

existe un nuevo tipo llamado ERROR_TYPES. Es cierto que REGULAR_ERR cede a 1, pero la conversión de este tipo a int debería producir una advertencia de conversión (si configura su comstackdor con una gran verbosidad).

Resumen: ambos son parecidos, pero cuando se utiliza enum se beneficia de la verificación de tipo y al usar define simplemente reemplaza cadenas de código.

Generalmente, se prefiere preferir los votos en #define donde tenga sentido usar una enumeración:

  • Los depuradores pueden mostrarle el nombre simbólico del valor de una enum (” openType: OpenExisting “, en lugar de ” openType: 2
  • Obtienes protección un poco más de los conflictos de nombres, pero esto no es tan malo como lo fue (la mayoría de los comstackdores advierten sobre re #define ition.

La mayor diferencia es que puedes usar enumeraciones como tipos:

 // Yeah, dumb example enum OpenType { OpenExisting, OpenOrCreate, Truncate }; void OpenFile(const char* filename, OpenType openType, int bufferSize); 

Esto le proporciona comprobación de tipos de parámetros (no puede mezclar OpenType y bufferSize tan fácilmente), y hace que sea más fácil encontrar qué valores son válidos, haciendo que sus interfaces sean mucho más fáciles de usar. ¡Algunos IDE pueden incluso darle la terminación del código intellisense !

Siempre es mejor usar una enumeración si es posible. Al usar una enumeración, el comstackdor obtiene más información sobre su código fuente, el comstackdor nunca ve una definición de preprocesador y, por lo tanto, lleva menos información.

Para implementar, por ejemplo, un conjunto de modos, el uso de una enumeración hace posible que el comstackdor capte case estados faltantes en un conmutador, por ejemplo.

enum puede agrupar múltiples elementos en una categoría:

 enum fruits{ apple=1234, orange=12345}; 

mientras que #define solo puede crear constantes no relacionadas:

 #define apple 1234 #define orange 12345 

#define es un comando de preprocesador, enum está en el lenguaje C o C ++.

Siempre es mejor usar enumeraciones sobre #define para este tipo de casos. Una cosa es seguridad tipo. Otra es que cuando tienes una secuencia de valores solo tienes que dar el comienzo de la secuencia en la enumeración, los otros valores obtienen valores consecutivos.

 enum { ONE = 1, TWO, THREE, FOUR }; 

en lugar de

 #define ONE 1 #define TWO 2 #define THREE 3 #define FOUR 4 

Como nota al margen, todavía hay algunos casos en los que es posible que deba usar #define (normalmente para algún tipo de macros, si necesita poder construir un identificador que contenga la constante), pero eso es una especie de macro magia negra , y muy raro que sea el camino a seguir. Si vas a estas extremidades, probablemente deberías usar una plantilla de C ++ (pero si estás atrapado con C …).

Si solo quieres esta constante única (digamos para buffersize) entonces no usaría una enumeración, sino una definición. Yo usaría enumeraciones para cosas como valores de retorno (que significan diferentes condiciones de error) y donde sea que necesitemos distinguir diferentes “tipos” o “casos”. En ese caso, podemos usar una enumeración para crear un nuevo tipo que podamos usar en prototipos de funciones, etc., y luego el comstackdor puede verificar mejor ese código.

Además de todo lo que ya está escrito, uno dijo pero no se mostró y, en cambio, es interesante. P.ej

 enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP }; //... void do_action( enum action anAction, info_t x ); 

Considerar la acción como un tipo hace que todo sea más claro. Usando definir, hubieras escrito

 void do_action(int anAction, info_t x); 

Para los valores constantes integrales he llegado a preferir enum a #define . No parece haber inconvenientes para usar enum (descontando la minúscula desventaja de escribir un poco más), pero tiene la ventaja de que enum puede determinar, mientras que los identificadores #define tienen scope global que lo toca todo.

Usar #define no suele ser un problema, pero como no hay inconvenientes para enum , voy con eso.

En C ++ generalmente también prefiero que enum const int aunque en C ++ se puede usar const int en lugar de un valor entero literal (a diferencia de C) porque enum es portatil a C (que todavía trabajo mucho).

Si tiene un grupo de constantes (como “Días de la semana”) sería preferible la enumeración, porque muestra que están agrupadas; y, como dijo Jason, son seguros para el tipo. Si se trata de una constante global (como el número de versión), es más de lo que usaría un #define ; aunque este es el tema de mucho debate.

Además de los buenos puntos enumerados anteriormente, puede limitar el scope de las enumeraciones a una clase, estructura o espacio de nombres. Personalmente, me gusta tener el número mínimo de símbolos relevantes en el scope en un momento dado, que es otra razón para usar enumeraciones en lugar de #defines.

Otra ventaja de una enumeración sobre una lista de define es que los comstackdores (al menos gcc) pueden generar una advertencia cuando no se verifican todos los valores en una instrucción switch. Por ejemplo:

 enum { STATE_ONE, STATE_TWO, STATE_THREE }; ... switch (state) { case STATE_ONE: handle_state_one(); break; case STATE_TWO: handle_state_two(); break; }; 

En el código anterior, el comstackdor puede generar una advertencia de que no todos los valores de la enumeración se manejan en el conmutador. Si los estados se hicieron como # define’s, este no sería el caso.

las enumeraciones se utilizan más para enumerar algún tipo de conjunto, como días en una semana. Si necesita solo un número constante, const int (o double, etc.) sería definitivamente mejor que enum. Personalmente, no me gusta #define (al menos no para la definición de algunas constantes) porque no me da seguridad de tipo, pero puedes usarla si te conviene más.

La creación de una enumeración crea no solo literales sino también el tipo que agrupa estos literales: esto agrega semántica a su código que el comstackdor puede verificar.

Además, al utilizar un depurador, tiene acceso a los valores de los literales enum. Este no es siempre el caso con #define.

Enum:

1. Generalmente se usa para valores múltiples

2. En enum hay dos cosas: una es nombre y otra es el valor del nombre nombre debe distinguirse pero el valor puede ser igual. Si no definimos valor, entonces el primer valor de enum nombre es 0 segundo valor es 1, y así sucesivamente, a menos que explícitamente se especifican los valores.

3. Pueden tener tipo y el comstackdor puede escribir verificarlos

4. Hacer que la depuración sea fácil

5. Podemos limitar el scope de la misma a una clase.

Definir:

1. Cuando tenemos que definir solo un valor

2. Por lo general, reemplaza una cadena por otra cadena.

3. Su scope es global, no podemos limitar su scope

En general, tenemos que usar enum

Hay poca diferencia. El Estándar C dice que las enumeraciones tienen un tipo integral y que las constantes de enumeración son de tipo int, por lo que ambas pueden mezclarse libremente con otros tipos integrales, sin errores. (Si, por otro lado, dicha intermezcla no se permitiera sin conversiones explícitas, el uso juicioso de las enumeraciones podría detectar ciertos errores de progtwigción).

Algunas de las ventajas de las enumeraciones son que los valores numéricos se asignan automáticamente, que un depurador puede mostrar los valores simbólicos cuando se examinan las variables de enumeración y que obedecen al scope del bloque. (Un comstackdor también puede generar advertencias no fatales cuando las enumeraciones se mezclan indiscriminadamente, ya que hacerlo todavía se puede considerar como un mal estilo aunque no sea estrictamente ilegal.) Una desventaja es que el progtwigdor tiene poco control sobre esas advertencias no fatales; algunos progtwigdores también resienten no tener control sobre los tamaños de las variables de enumeración.

Si bien varias respuestas anteriores recomiendan usar enum por varias razones, me gustaría señalar que el uso de define tiene una ventaja real al desarrollar interfaces. Puede presentar nuevas opciones y puede permitir que el software las use condicionalmente.

Por ejemplo:


     #define OPT_X1 1 / * introducido en la versión 1 * /
     #define OPT_X2 2 / * introducido en la versión 2 * /

Entonces el software que se puede comstackr con cualquier versión puede hacer


     #ifdef OPT_X2
     int flags = OPT_X2;
     #más
     int flags = 0;
     #terminara si

Durante una enumeración, esto no es posible sin un mecanismo de detección de características en tiempo de ejecución.