25 votes

Ce qui rend un meilleur constante dans C, une macro ou un enum?

Je suis confus au sujet de quand utiliser des macros ou des enums. Les deux peuvent être utilisés comme des constantes, mais quelle est la différence entre eux et quel est l'avantage de l'un? C'est en quelque sorte lié à compilateur niveau ou pas?

22voto

dasblinkenlight Points 264350

En termes de lisibilité, les énumérations de prendre de meilleures constantes de macros, parce que les valeurs correspondantes sont regroupées. En outre, enum définit un nouveau type, afin que les lecteurs de votre programme serait plus facile de déterminer ce qui peut être transmise au paramètre correspondant.

Comparer

#define UNKNOWN  0
#define SUNDAY   1
#define MONDAY   2
#define TUESDAY  3
...
#define SATURDAY 7

pour

typedef enum {
    UNKNOWN
,   SUNDAY
,   MONDAY
,   TUESDAY
,   ...
,   SATURDAY
} Weekday;

Il est beaucoup plus facile à lire le code comme ceci

void calendar_set_weekday(Weekday wd);

que ce

void calendar_set_weekday(int wd);

parce que vous savez qui constantes c'est OK pour passer.

16voto

Ziffusion Points 3783

Une macro est un préprocesseur chose, et le code compilé n'a aucune idée sur les identifiants que vous créez. Ils ont déjà été remplacé par le préprocesseur avant le code frappe le compilateur. Un enum est un moment de la compilation de l'entité, et le code compilé conserve des informations complètes sur le symbole, qui est disponible dans le débogueur (et d'autres outils).

Préférez les énumérations (si vous le pouvez).

7voto

Jens Points 17702

Remarque il y a quelques différences entre les macros et les énumérations, et l'une de ces propriétés peut faire (de l'onu)approprié comme une constante en particulier.

  • les énumérations sont signés (compatible avec int). Dans un contexte où un type non signé est requis (pensons en particulier à des opérations bit à bit!), les énumérations sont out.
  • si long long est plus large que int, grandes constantes ne rentre pas dans un enum.
  • La taille d'un enum est - sizeof(int). Pour les tableaux de petites valeurs (jusqu'à-dire, CHAR_MAX), vous voudrez peut-être un char foo[] plutôt qu'un enum foo[] tableau.
  • les énumérations sont partie intégrante des nombres. Vous ne pouvez pas avoir d' enum funny_number { 3.14, 2.71 }.
  • les énumérations sont un C89 fonction; K&R compilateurs (il est vrai que l'ancien), ne les comprends pas.

4voto

Kaz Points 18072

En C, il est préférable d'utiliser les énumérations réel d'énumérations: quand une variable peut contenir l'une des valeurs multiples qui peut être donné des noms. L'un des avantages d'énumérations, c'est que le compilateur peut effectuer des vérifications au-delà de ce que la langue exige, à l'instar d'un interrupteur déclaration sur le type enum n'est pas absente de l'un des cas. L'enum identificateurs également se propager dans les informations de débogage. Dans un débogueur, vous pouvez voir le nom de l'identificateur de la valeur de l'enum variable, plutôt que de simplement la valeur numérique.

Les énumérations peuvent être utilisés seulement pour les effets secondaires de la création de constantes symboliques de type intégral. Par exemple:

enum { buffer_size = 4096 };  /* we don't care about the type */

cette pratique n'est pas répandue. Pour une chose, buffer_size sera utilisé comme un entier et non pas comme un type énuméré. Un débogueur ne sera pas rendu 4096 en buffer_size, parce que la valeur ne sera pas représenté comme le type énuméré. Si vous déclarez quelques - char array[max_buffer_size]; alors sizeof array ne s'affiche pas comme buffer_size. Dans cette situation, l'énumération constante disparaît au moment de la compilation, il pourrait aussi bien être une macro. Et il y a des inconvénients, comme n'étant pas en mesure de contrôler son type exact. (Il pourrait y avoir un petit avantage dans certaines situations où la sortie du prétraitement des étapes de la traduction est d'être capturé en tant que texte. Une macro se transforment en 4096, alors qu' buffer_size reste buffer_size).

Un symbole de préprocesseur nous permet de faire cela:

#define buffer_size 0L /* buffer_size is a long int */

Notez que les différentes valeurs de C <limits.h> comme UINT_MAX sont des symboles de préprocesseur et pas enum symboles, avec de bonnes raisons, parce que ces désignations doivent avoir une déterminées avec précision le type. Un autre avantage d'un symbole de préprocesseur est que l'on peut tester sa présence, ou même de prendre des décisions en fonction de sa valeur:

#if ULONG_MAX > UINT_MAX 
/* unsigned long is wider than unsigned int */
#endif

Bien sûr, nous pouvons tester les constantes énumérées aussi, mais pas de la façon que nous pouvons changer les déclarations globales basées sur le résultat.

Les énumérations sont également mal adapté pour les masques de bits:

enum modem_control { mc_dsr = 0x1, mc_dtr = 0x2, mc_rts = 0x4, ... }

il n'a tout simplement pas de bon sens parce que quand les valeurs sont combinées avec un OU binaire"/", ils produisent une valeur qui est en dehors de ce type. Ce code provoque un mal de tête, trop, s'il est porté à C++, qui a (un peu plus) de type sécurisé énumérations.

3voto

AndreyT Points 139512

Si la macro est mise en œuvre correctement (j'.e il ne souffre pas de l'associativité des problèmes lorsque substitué), alors il n'y a pas beaucoup de différence dans le applicabilité entre macro et enum constantes dans les situations où les deux sont applicables, c'est à dire dans la situation où vous avez besoin de signer des constantes entières en particulier.

Toutefois, dans le cas général, les macros de fournir beaucoup plus de souplesse de la fonctionnalité. Les Enums imposer un type spécifique sur votre constantes: ils auront type int (ou, éventuellement, de plus signé de type entier), et ils seront toujours être signé. Avec des macros, vous pouvez utiliser la constante de la syntaxe, des suffixes et/ou explicites, les conversions de type pour produire une constante de tout type.

Les Enums fonctionne mieux lorsque vous avez un groupe de étroitement associée séquentielle des constantes entières. Ils fonctionnent particulièrement bien lorsque vous n'avez pas de soins sur les valeurs des constantes à tous, c'est à dire lorsque vous ne se soucient que de leur avoir quelques bon comportement de valeurs uniques. Dans tous les autres cas, les macros sont un meilleur choix (ou en fait le seul choix).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X