2010-06-28 13 views
12

Duplicar posible:
Why use enum when #define is just as efficient?#define o enum?

Al programar en C, ¿es mejor la práctica de utilizar declaraciones #define o enumeraciones de estados de una máquina de estados?

+6

El número de preguntas cuyas respuestas son "preferir un' # define' "es sorprendentemente bajo. – Stephen

+1

@Stephen: Principalmente porque muchos carteles están bloqueados en modo C++, mientras que la pregunta es acerca de C. La diferencia entre C y C++ en este sentido es bastante grande. De hecho, en C en la mayoría de los casos, debería preferir '# define', pero en este caso específico (máquina de estados)' enum' es de hecho un mejor enfoque. – AnT

+0

duplicado de algo que yo recuerde. Tal vez la especificación "para estados en una máquina de estado", lo cambia un poco, pero no hay razón para considerar una "máquina de estado" una aplicación diferente de lo que #define o enumeraciones se puede usar para ... – ShinTakezou

Respuesta

12

Dado que los estados son elementos relacionados, creo que es mejor tener una enumeración que los defina.

8

Prefiero enum. Son más compactos y son 'más seguros'. También puede implicar el orden en una enumeración, que podría ser útil en una máquina de estados. #defines deben evitarse si es posible, ya que sobrescribirán todas las ocurrencias en el código fuente, lo que puede dar lugar a algunas acciones no deseadas que son difíciles de depurar.

2

#define directivas pueden tener muchas consecuencias imprevistas y no siguen reglas comunes de alcance. Use enumeraciones cuando tenga datos relacionados.

Más información: http://www.embedded.com/columns/programmingpointers/9900402?_requestid=341945 [C++ material, pero todavía marginalmente pertinente]

+0

La información que linked es sobre C++, no C. La diferencia entre C y C++ cuando se trata de elegir un método para definir constantes es * ENORME *. – AnT

+0

independientemente, si es posible, las enumeraciones son preferibles porque son tipo seguras y no sobrescriben ningún otro código –

+1

@Nathan Fellman: No. En C, 'enum' es preferible solo cuando estamos trabajando con un grupo natural de constantes. En todos los demás casos, es '# define' y solo' # define'. – AnT

2

Si enum es apoyado por su compilador, entonces eso sería preferido. En su defecto, por supuesto, use #define. Todos los compiladores de C++ y los compiladores de C modernos deben admitir enum, pero los compiladores anteriores (especialmente los que se dirigen a plataformas integradas) pueden no ser compatibles con enum.

Si tiene que usar #define Asegúrese de definir sus constantes con paréntesis, para evitar errores de preprocesador:

#define RED_STATE (1) 
#define YELLOW_STATE (2) 
#define GREEN_STATE (3) 
9

No hay una respuesta definitiva. enum le ofrece el alcance y la asignación automática de valores, pero no le da ningún control sobre el tipo constante (siempre signed int). #define ignora el alcance, pero le permite utilizar mejores funciones de tipeo: le permite elegir el tipo de constante (ya sea mediante el uso de sufijos o mediante la inclusión de un molde explícito en la definición).

Por lo tanto, elija usted mismo lo que es más importante para usted. Para una máquina de estado, enum podría ser una mejor opción, a menos que tenga una buena razón para controlar el tipo.

+0

La mayoría de los compiladores le permiten especificar el tamaño de las enumeraciones. –

+1

@Adam Shiemke: ... que normalmente es un entorno global. Y estoy hablando del tipo, no del tamaño. Ni C ni C++ (en su forma actual) le ofrecen ningún control significativo sobre el tipo de valores enum. – AnT

+0

AFAIR C99 no le ofrece ninguna opción para el tipo de constantes 'enum', es decir, las arregla para que sean constantes de tipo' signed int'. Un tipo 'enum' en sí mismo puede tener un ancho diferente, y depende del compilador elegir un tamaño conveniente que se ajuste a todas las constantes definidas con el tipo. Entonces, en particular, puede tener ese tamaño más pequeño que para 'int', pero generalmente no es más grande. –

0

enum es grande cuando usted tiene opciones exclusivas, pero no se puede utilizar para definir las banderas del campo de bits, como esto:

#define SQ_DEFAULT 0x0 
#define SQ_WITH_RED 0x1 
#define SQ_WITH_BLUE 0x2 

void paint_square(int flags); 

A continuación, se puede pintar cuadrado rojo-azul con:

paint_square(SQ_WITH_RED | SQ_WITH_BLUE); 

... que no se puede con enum.

+0

sí, usted puede: 'enum (a = 1, b = 2, c = 4, d = 5)' –

+2

¿No puede? Por supuesto, puede: 'enum {SQ_DEFAULT = 0x0, SQ_WITH_RED = 0x1, SQ_WITH_BLUE = 0x2}'. El problema aquí es que con flags es mejor usar un tipo * unsigned *. Pero de lo contrario, enum funcionará. – AnT

+1

¡Claro que puedes! 'enum Color {default = 0x0, red = 0x1, blue = 0x2};' y posterior 'paint_square (red | blue)' – Mecki

36

Técnicamente no importa. El compilador es muy probable que incluso crear código de máquina idéntico para ambos casos, pero una enumeración tiene tres ventajas:

  1. Uso de la combinación compilador + depurador derecha, el depurador se escribe las variables de enumeración por su nombre enumeración y no por su número. Entonces, "StateBlahBlup" se lee mucho mejor que "41", ¿no es así?

  2. No le ha dado explícitamente a cada estado un número, el compilador hace la numeración por usted si lo permite. Supongamos que ya tiene 20 estados y desea agregar un nuevo estado en el medio, en caso de definir, debe hacer todas las renumeraciones por su cuenta. En caso de enumeración, puede simplemente agregar el estado y el compilador volverá a numerar todos los estados debajo de este nuevo estado.

  3. Puede decirle al compilador que le advierta si una instrucción switch no maneja todos los posibles valores enum, p. porque olvidó manejar algunos valores o porque la enumeración se extendió pero olvidó actualizar también las instrucciones de conmutación que manejan valores enum (aunque no advertirá si hay un caso default, ya que todos los valores no manejados terminan explícitamente en el caso predeterminado) .

+5

Buena respuesta ... +1 – wrapperm

0

Puedes usar lo que quieras y te guste.

Todavía como todos dicen que también me gustaría sumarme como votante para Enums.

Enumerar siempre debe ser preferible si está utilizando datos relacionados, como en el caso de una máquina de estados, también puede definir el orden en enumeraciones que ayudarán a implementar State Machine.

Otras enums mantendrán su programa seguro, ya que todas las enumeraciones serán de su tipo solo, por lo que evitarán posibles confusiones.

#define no se debe utilizar en el caso de una máquina de estado o datos relacionados. De todos modos, esa es mi sugerencia, pero no hay una regla dura y rápida.

También me gustaría agregar un punto más que las enumeraciones agregarán más legibilidad y comprensibilidad a su código si se utilizan en el futuro o si alguien más las lee. Es un punto importante cuando tiene un programa muy grande y hay muchas # definiciones en el programa además de las que está utilizando para su Máquina de estado.

1

Puede hacer este truco para que el compilador compruebe el tipo de valor #define.

#define VALUE_NAME ((TYPE_NAME) 12) 

Sin embargo, el verdadero problema de la #define es que puede ser redefinido en el código de aplicación. (Por supuesto, el compilador lo advertirá al respecto.)