Pregunta

¿Cuál es la diferencia entre usar una declaración de definición y una instrucción enum en C / C ++ (y hay alguna diferencia cuando se usa con C o C ++)?

Por ejemplo, cuando se debe usar

enum {BUFFER = 1234}; 

sobre

#define BUFFER 1234   
¿Fue útil?

Solución

enum define un elemento sintáctico.

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

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

Otros consejos

#define las declaraciones son manejadas por el preprocesador antes de que el compilador vea el código, así que es básicamente 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 el tipo y el compilador puede verificarlos con el tipo.

2 / Ya que están disponibles para el compilador, la información de los símbolos puede pasarse al depurador, lo que facilita la depuración.

Definir es un comando de preprocesador, es como hacer " reemplazar todos " en su editor, puede reemplazar una cadena por otra y luego compilar 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 lanzamiento (si configura su compilador a una alta verbosidad).

Resumen: ambos son iguales, pero al usar la enumeración se beneficia de la verificación de tipos y al usarla, simplemente se reemplazan las cadenas de código.

Generalmente, las enumeraciones se prefieren a #define donde sea más lógico usar una enumeración:

  • Los depuradores pueden mostrarle el nombre simbólico del valor de enum (" openType: OpenExisting " ;, en lugar de " openType: 2 "
  • Obtienes un poco más de protección contra los choques de nombres, pero esto no es tan malo como lo fue (la mayoría de los compiladores advierten sobre la 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 permite verificar los tipos de parámetros (no puede mezclar openType y bufferSize con la misma facilidad) y facilita la búsqueda de qué valores son válidos, lo que hace que las interfaces sean mucho más fáciles de usar. ¡Algunos IDE pueden incluso proporcionarle el código de intellisense !

Siempre es mejor usar una enumeración si es posible. El uso de una enumeración le da al compilador más información sobre el código fuente, el compilador nunca ve una definición de preprocesador y, por lo tanto, contiene menos información.

Para la implementación, por ejemplo. un montón de modos, el uso de una enumeración hace posible que el compilador detecte las declaraciones de caso que faltan en un switch, por ejemplo.

la enumeración puede agrupar varios elementos en una categoría:

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

mientras #define solo puede crear constantes no relacionadas:

#define apple 1234
#define orange 12345

#define es un comando del preprocesador, la enumeración está en el lenguaje C o C ++.

Siempre es mejor usar enumeraciones sobre #define para este tipo de casos. Una cosa es el tipo de seguridad. 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 tenga que usar #define (normalmente para algún tipo de macros, si necesita poder construir un identificador que contenga la constante), pero eso es algo macro magia negra, y muy, muy raro para ser el camino a seguir. Si vas a estas extremidades, probablemente deberías usar una plantilla de C ++ (pero si estás atascado con C ...).

Si solo desea esta constante única (por ejemplo, para buffersize), no usaría una enumeración, sino una definición. Usaría enumeraciones para cosas como valores de retorno (que significan diferentes condiciones de error) y donde sea necesario distinguir diferentes tipos de " " o " casos " ;. En ese caso, podemos usar una enumeración para crear un nuevo tipo que podamos usar en los prototipos de funciones, etc., y luego el compilador puede verificar la integridad de ese código.

Además de todo lo que ya está escrito, uno dijo pero no se muestra y es interesante. Por ejemplo,

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 deja las cosas más claras. Usando define, habrías escrito

void do_action(int anAction, info_t x);

Para valores constantes integrales, prefiero enum sobre #define . Parece que no hay desventajas al usar enum (descontando la minúscula desventaja de escribir un poco más), pero tiene la ventaja de que enum puede tener un ámbito, mientras que Los identificadores de #define tienen un alcance global que lo controla todo.

El uso de #define no suele ser un problema, pero como no hay inconvenientes para enum , sigo con eso.

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

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

Además de los puntos buenos mencionados anteriormente, puede limitar el alcance 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 alcance en cualquier momento, lo cual es otra razón para usar enumeraciones en lugar de #defines.

Otra ventaja de una enumeración sobre una lista de definiciones es que los compiladores (al menos gcc) pueden generar una advertencia cuando no se verifican todos los valores en una declaración de cambio. 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 compilador puede generar una advertencia de que no todos los valores de la enumeración se manejan en el conmutador. Si los estados se hicieran como # define, este no sería el caso.

Las enumeraciones

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

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 tu código que el compilador puede verificar.

Además, cuando utiliza un depurador, tiene acceso a los valores de los literales de enumeración. Este no es siempre el caso con #define.

Si bien varias de las respuestas anteriores recomiendan usar enumeración por varias razones, me gustaría señalar que el uso de define tiene una ventaja real al desarrollar interfaces. Puede introducir nuevas opciones y puede permitir que el software las utilice de forma condicional.

Por ejemplo:

    #define OPT_X1 1 /* introduced in version 1 */
    #define OPT_X2 2 /* introduced in version  2 */

Luego, el software que puede compilarse con cualquiera de las versiones que puede hacer

    #ifdef OPT_X2
    int flags = OPT_X2;
    #else
    int flags = 0;
    #endif

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

Enumeración:

1. Generalmente se utiliza para varios valores

2. En la enumeración hay dos cosas, una es el nombre y la otra es el valor del nombre el nombre debe distinguirse, pero el valor puede ser el mismo. 1, y así sucesivamente, a menos que se especifique explícitamente un valor.

3. Pueden tener el tipo y el compilador puede escribir, verlos

4. Facilita la depuración

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

Definir:

1. Cuando tenemos que definir un solo valor

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

3. El alcance es global, no podemos limitar su alcance

En general, tenemos que usar enumeración

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

Algunas 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 la enumeración, y que obedecen el alcance del bloque. (Un compilador también puede generar advertencias no fatales cuando las enumeraciones se mezclan de manera indiscriminada, ya que al hacerlo aún se puede considerar un estilo malo aunque no sea estrictamente ilegal). Una desventaja es que el programador tiene poco control sobre esas advertencias no fatales; algunos programadores también resienten no tener control sobre los tamaños de las variables de enumeración.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top