2008-09-25 9 views
44

¿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++)?Diferencia entre Enum y Definir declaraciones

Por ejemplo, cuando debe uno utilizar

enum {BUFFER = 1234}; 

sobre

#define BUFFER 1234 

Respuesta

55

enum define un elemento sintáctico.

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

Generalmente son preferibles 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, una parte del código puede redefinir un #define hecho por otro. Esto puede ser difícil de rastrear.

+21

También se puede poner en enumeraciones espacios de nombres, mientras que las macros no pueden ser. –

+0

Sin embargo, las macros se pueden configurar más fácilmente fuera del código fuente mismo (por ejemplo, desde dentro del comando de compilación) –

8

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

enumeración es un caso especial de tipo, por ejemplo, si se escribe:

enum ERROR_TYPES 
{ 
    REGULAR_ERR =1, 
    OK =0 
} 

existe un nuevo tipo llamado tipos_error. 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 el compilador con una gran verbosidad).

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

+1

"volcar de este tipo a int" está de vuelta al frente, creo; C++ trata las enumeraciones como especializaciones de int. –

1

Si tiene un grupo de constantes (como "Días de la semana") sería preferible la enumeración, ya que 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), eso es más de lo que usaría un #define para; aunque este es el tema de mucho debate.

14

#define las declaraciones son manejadas por el preprocesador antes de que el compilador vea el código, por lo 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 tipo y el compilador puede verificarlos.

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

5

enumeraciones son generalmente preferimos sobre #define allí donde tiene sentido utilizar una enumeración:

  • depuradores se puede mostrar el nombre simbólico de un valor enum s ("openType: OpenExisting", en lugar de 'openType: 2'
  • se obtiene un poco más de protección contra colisiones 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 yo u puede utilizar como enumeraciones tipos:

// Yeah, dumb example 
enum OpenType { 
    OpenExisting, 
    OpenOrCreate, 
    Truncate 
}; 

void OpenFile(const char* filename, OpenType openType, int bufferSize); 

Esto le da la comprobación de tipos de parámetros (no se puede mezclar OpenType y bufferSize tan fácilmente), y hace que sea fácil encontrar qué valores son válidos, por lo que las interfaces mucho más fácil de usar. Algunos IDEs incluso pueden darle intellisense finalización del código!

1

Además de los buenos puntos enumerados 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 un momento dado, que es otra razón para usar enumeraciones en lugar de #defines.

1

Otra ventaja de una enumeración sobre una lista de define es que los compiladores (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 compilador es capaz de generar una advertencia de que no todos los valores de la enumeración se manejan en el interruptor. Si los estados se hicieron como # define's, este no sería el caso.

4

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

Para la implementación, p. un conjunto de modos, usando una enumeración hace posible que el compilador capture las case declaraciones que faltan en un interruptor, por ejemplo.

1

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 el doble, etc.) sería definitivamente mejor que enum. Personalmente no me gusta el #define (al menos no para la definición de algunas constantes) porque no me da seguridad de tipo, pero por supuesto puede usarlo si le conviene más.

2

Si solo quieres esta constante única (por ejemplo 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 compilador puede verificar mejor ese código.

3

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

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

mientras #define sólo puede crear constantes no relacionados:

#define apple 1234 
#define orange 12345 
+0

Gracias por la respuesta más útil en internet. (y realmente no estoy bromeando) –

3

#define es un comando preprocesador, enum es en el C o Lenguaje C++.

Siempre es mejor utilizar 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 lateral, todavía hay algunos casos en los que pueda tener para usar #define (normalmente algún tipo de macros, si tiene que ser capaz de construye un identificador que contiene 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 ...).

2

Además de todo lo que ya está escrito, uno dijo pero no se mostró y en su lugar 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. El uso de definir, que habría escrito

void do_action(int anAction, info_t x); 
2

Para valores constantes integrales que he llegado a preferir enum sobre #define. No parece haber desventajas al usar enum (descontando la minúscula desventaja de escribir un poco más), pero tiene la ventaja de que enum tiene un alcance, mientras que los identificadores #define tienen alcance global que lo detiene todo.

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

En C++ I también generalmente prefieren enum a const int pesar de que en C++ un const int se puede utilizar en lugar de un valor entero literal (a diferencia de C) porque enum es portátil a C (que todavía trabajo en un lote).

+0

Si uno, si trabaja en sistemas integrados, ¿no sería la memoria adicional consumida por la enumeración un inconveniente (menor)? Un #define, siendo esencialmente un reemplazo del preprocesador no consume la memoria adicional en el segmento de datos. – Demi

+3

@Demi: los enums no ocupan espacio, solo son nombres para números. Si declara una variable del tipo enum, esa variable ocupará espacio, pero eso es lo mismo que declarar una variable de tipo int (o lo que sea) e inicializarla o asignarla con una macro. –

+0

+1 Para 'For * integral * valores constantes que he llegado a preferir', hay situaciones donde se necesita especificar constantes de coma flotante (por ejemplo, relaciones) y para esas situaciones, las enumeraciones son inútiles –

1

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

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

0

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 permitía sin conversiones explícitas, el uso juicioso de las enumeraciones podría detectar ciertos errores de programació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 el alcance del bloque. (Un compilador 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 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.

0

Si bien varias respuestas anteriores recomiendan utilizar 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 /* introduced in version 1 */ 
    #define OPT_X2 2 /* introduced in version 2 */ 

Entonces software que puede ser compilado con ya sea la versión que puede hacer

 

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

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

1

Enum:

1. utiliza generalmente para varios valores

2. En enum hay dos que uno es el nombre y la otra es el valor del nombre del nombre debe ser distinguido pero el valor puede ser mismo.Si no definimos el valor, entonces el primer valor del nombre enum es 0 segundo valor es 1, y así sucesivamente, a menos que se especifique explícitamente el valor.

3. Pueden tener el tipo y el compilador puede escribir comprobar a

4. Hacer depuración fácil

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

Definir:

1. Cuando tenemos que definir un solo valor

2. Por lo general reemplazar una cadena a otra cadena.

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

En general, tienen que utilizar enumeración

Cuestiones relacionadas