68 votes

#define est-il interdit par une ou plusieurs normes industrielles spécifiques ?

Je suis un étudiant en première année d'informatique et mon professeur a dit #define est interdit dans les normes industrielles, tout comme #if , #ifdef , #else et quelques autres directives du préprocesseur.

Il a utilisé le mot "interdit" en raison d'un "comportement inattendu". Est-ce qu'un démonstration de principe de ces problèmes existent, ce qui est documenté ou cité dans une norme commerciale particulière ( comme un ISO ), et est la raison d'être d'une convention d'interdiction.

141voto

Jonathan Leffler Points 299946

C'est la première fois que j'en entends parler.

Non ; #define etc. sont largement utilisés. Parfois trop largement utilisés, mais bel et bien utilisés. Il y a des endroits où la norme C impose l'utilisation de macros - vous ne pouvez pas les éviter facilement. Par exemple, le §7.5 Erreurs <errno.h> dit :

Les macros sont

     EDOM
     EILSEQ
     ERANGE

qui se développent en expressions constantes entières de type int , des valeurs positives distinctes, et qui conviennent à l'utilisation de #if directives de prétraitement ;

Vous pourriez vérifier le MISRA C (2012) ; cela tend à proscrire des choses, mais même cela reconnaît que #define et al sont parfois nécessaires (la section 8.20, les règles 20.1 à 20.14 couvrent le préprocesseur C).

Le GSFC de la NASA (Goddard Space Flight Center) Normes de codage C dites simplement :

Les macros ne doivent être utilisées que lorsque cela est nécessaire. Une utilisation excessive des macros peut rendre le code plus difficile à lire et à maintenir parce que le code ne se lit plus ou ne se comporte plus comme le C standard.

La discussion qui suit cette déclaration introductive illustre l'utilisation acceptable des macros de fonction.

El Norme de codage CERT C contient un certain nombre de directives concernant l'utilisation du préprocesseur, et implique que vous devriez minimiser l'utilisation du préprocesseur, mais ne l'interdit pas.

M. Stroustrup aimerait que le préprocesseur ne soit plus pertinent en C++, mais cela n'a pas encore eu lieu. Comme Peter notes Certaines normes C++, telles que la norme Normes de codage JSF AV C++ ( Joint Strike Fighter, véhicule aérien ) datant d'environ 2005, imposent une utilisation minimale du préprocesseur C. Essentiellement, les règles C++ de JSF AV le limitent à #include et le #ifndef XYZ_H / #define XYZ_H / / #endif qui empêche les inclusions multiples d'un même en-tête. Le C++ dispose de certaines options qui ne sont pas disponibles en C - notamment une meilleure prise en charge des constantes typées qui peuvent alors être utilisées là où le C ne le permet pas. Voir aussi static const vs #define vs enum pour une discussion sur ces questions.

C'est une bonne idée de minimiser l'utilisation du préprocesseur - il est souvent malmené au moins autant qu'il est utilisé (voir la section Boost préprocesseur library" pour illustrer jusqu'où vous pouvez aller avec le préprocesseur C).

Résumé

Le préprocesseur fait partie intégrante de C et de #define y #if etc. ne peuvent être totalement évitées. La déclaration du professeur dans la question n'est pas valable en général : #define est interdit dans les normes industrielles, tout comme #if , #ifdef , #else et quelques autres macros est, au mieux, une affirmation exagérée, mais qui pourrait être étayée par une référence explicite à des normes industrielles spécifiques (mais les normes en question ne comprennent pas la norme ISO/IEC 9899:2011 - la norme C).


Notez que David Hammen a information fournie sur un standard de codage C spécifique - le Norme de codage C du JPL - qui interdit beaucoup de choses que beaucoup de gens utilisent en C, y compris la limitation de l'utilisation du préprocesseur C (et la limitation de l'utilisation de l'allocation dynamique de mémoire, et l'interdiction de la récursion - lisez-le pour voir pourquoi, et décidez si ces raisons sont pertinentes pour vous).

33voto

Peter Points 4026

Non, l'utilisation de macros n'est pas interdite.

En fait, l'utilisation de #include Les gardes dans les fichiers d'en-tête sont une technique courante, souvent obligatoire et encouragée par les directives de codage acceptées. Certaines personnes prétendent que #pragma once est une alternative à cela, mais le problème est que #pragma once - par définition, puisque les pragmas sont un crochet fourni par la norme pour les extensions spécifiques au compilateur - est non standard, même s'il est supporté par un certain nombre de compilateurs.

Cela dit, il existe un certain nombre de directives industrielles et de pratiques encouragées qui découragent activement toute utilisation de macros autres que #include gardes à cause des problèmes que les macros introduisent (non respect de la portée, etc). Dans le développement C++, l'utilisation de macros est désapprouvée encore plus fortement que dans le développement C.

Décourager l'utilisation d'un produit n'équivaut pas à l'interdire, car il est toujours possible de l'utiliser légitimement, par exemple en documentant une justification.

30voto

John Bode Points 33046

Certaines normes de codage peuvent décourager, voire interdire, l'utilisation de #define pour créer macros de type fonction qui prennent des arguments, comme

#define SQR(x) ((x)*(x))

car a) de telles macros ne sont pas sûres et b) quelqu'un va inévitablement écrire SQR(x++) ce qui est mauvais signe.

Certaines normes peuvent décourager ou interdire l'utilisation de #ifdef pour la compilation conditionnelle. Par exemple, le code suivant utilise la compilation conditionnelle pour imprimer correctement un fichier size_t valeur. Pour C99 et plus tard, vous utilisez le %zu spécificateur de conversion ; pour C89 et antérieures, vous utilisez %lu et convertit la valeur en unsigned long :

#if __STDC_VERSION__ >= 199901L
#  define SIZE_T_CAST
#  define SIZE_T_FMT "%zu"
#else
#  define SIZE_T_CAST (unsigned long)
#  define SIZE_T_FMT "%lu"
#endif
...
printf( "sizeof foo = " SIZE_T_FMT "\n", SIZE_T_CAST sizeof foo );

Certaines normes mai mandat qu'au lieu de faire cela, vous implémentez le module deux fois, une fois pour C89 et avant, une fois pour C99 et après :

/* C89 version */
printf( "sizeof foo = %lu\n", (unsigned long) sizeof foo );

/* C99 version */
printf( "sizeof foo = %zu\n", sizeof foo );

et ensuite laisser Faire (ou Fourmi ou l'outil de construction que vous utilisez) s'occupent de compiler et de lier la bonne version. Pour cet exemple, ce serait une surenchère ridicule, mais j'ai vu du code qui était un nid de rats intraçable composé de #ifdef que devrait ont fait en sorte que le code conditionnel soit réparti dans des fichiers séparés.

Cependant, je ne connais pas d'entreprise ou de groupe d'industrie qui a interdit l'utilisation pure et simple des instructions du préprocesseur.

16voto

Andrew Henle Points 5156

Les macros ne peuvent pas être "interdites". Cette affirmation est absurde. Littéralement.

Par exemple, l'article 7.5 Erreurs <errno.h> de la C Standard requiere l'utilisation de macros :

1 L'en-tête <errno.h> définit plusieurs macros, toutes relatives au signalement des conditions d'erreur.

2 Les macros sont

EDOM
EILSEQ
ERANGE

qui se développent en expressions constantes entières de type int , distinct valeurs positives distinctes, et qui conviennent à l'utilisation de #if prétraitement et

errno

qui se développe en une valeur lval modifiable de type int et le fil durée de stockage local, dont la valeur est fixée à un nombre positif d'erreurs positif par plusieurs fonctions de la bibliothèque. Si une définition de macro est supprimée afin d'accéder à un objet réel, ou qu'un programme définit un identifiant avec le nom errno le comportement est indéfini.

Donc, non seulement les macros sont un requis font partie du C, dans certains cas, ne pas les utiliser entraîne un comportement non défini.

15voto

Viktor Toth Points 437

Non, #define n'est pas interdite. L'utilisation abusive de #define Cependant, il peut être mal vu.

Par exemple, vous pouvez utiliser

#define DEBUG

dans votre code afin que, plus tard, vous puissiez désigner des parties de votre code pour la compilation conditionnelle à l'aide de la fonction #ifdef DEBUG à des fins de débogage uniquement. Je ne pense pas qu'une personne saine d'esprit veuille interdire une telle chose. Les macros définies à l'aide de #define sont aussi largement utilisés dans les programmes portables, pour activer/désactiver la compilation du code spécifique à la plate-forme.

Cependant, si vous utilisez quelque chose comme

#define PI 3.141592653589793

votre professeur peut, à juste titre, vous faire remarquer qu'il est bien mieux de déclarer PI comme une constante avec le type approprié, par exemple,

const double PI = 3.141592653589793;

car il permet au compilateur d'effectuer une vérification de type lorsque PI est utilisé.

De même (comme l'a mentionné John Bode ci-dessus), l'utilisation de macros de type fonction peut être désapprouvée, notamment en C++ où les modèles peuvent être utilisés. Ainsi, au lieu de

#define SQ(X) ((X)*(X))

envisager d'utiliser

double SQ(double X) { return X * X; }

ou, en C++, mieux encore,

template <typename T>T SQ(T X) { return X * X; }

Une fois encore, l'idée est qu'en utilisant les fonctionnalités du langage au lieu du préprocesseur, vous permettez au compilateur de vérifier le type et aussi (éventuellement) de générer un meilleur code.

Une fois que vous aurez suffisamment d'expérience en matière de codage, vous saurez exactement quand il est approprié d'utiliser #define . En attendant, je pense que c'est une bonne idée que votre professeur impose certaines règles et normes de codage, mais il est préférable qu'il en connaisse lui-même les raisons et soit en mesure de les expliquer. Une interdiction générale de #define est absurde.

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