30 votes

Est-il incorrect d'ajouter des directives de préprocesseur dans une macro de type fonction ?

Je sais que ma question est similaire à celui-ci ou celui-ci J'ai donc décidé de demander s'il est correct d'ajouter des directives de préprocesseur lorsqu'une macro de type fonction est appelée.

Dans mon cas, j'ai une macro de type fonction :

#define FUNC_MACRO(a, b)  // do something with the variables

et quelque part dans le code, je l'appelle avec une différence spécifique si une autre macro est définie :

// ...
FUNC_MACRO(aVal
#ifdef ANOTHER_MACRO
                + offset
#endif // ANOTHER_MACRO
           , bVal);
// ...

J'ai testé sur ma machine (linux, avec gcc 4.8) et cela a fonctionné correctement (avec et sans les directives du préprocesseur, et avec et sans ANOTHER_MACRO défini), mais est-ce sûr de le faire ?

J'ai lu le paragraphe 16.3/9 dans la réponse à la première question similaire, mais cela vaut-il aussi pour mon cas ?

45voto

R.. Points 93718

Le langage C laisse ce comportement non défini en 6.10.3 Remplacement des macros, ¶11 :

S'il y a des séquences de jetons de prétraitement dans la liste des arguments qui agiraient autrement comme des directives de prétraitement, le comportement est indéfini.

C'est donc une erreur de le faire.

GCC et peut-être d'autres compilations populaires ne le détectent pas, ce qui est probablement la raison pour laquelle de nombreux utilisateurs du langage ne le savent pas. J'ai rencontré ce problème lorsqu'une partie de mon code n'a pas réussi à se compiler sur PCC (et j'ai rapidement corrigé le bogue dans mon code).

Mise à jour : PJTraill a demandé dans les commentaires un cas où il serait "trompeur ou dénué de sens" d'avoir des directives de préprocesseur à l'intérieur d'une expansion de macro. En voici un évident :

    foo(a, b,
#ifdef BAR
        c);
#else
        d);
#endif

Je ne suis pas sûr qu'il aurait été plausible que la langue spécifie que équilibré les conditionnelles du préprocesseur à l'intérieur de l'expansion de la macro sont acceptables, mais je pense que vous rencontrerez des problèmes avec des ambiguïtés dans l'ordre dans lequel elles doivent être traitées.

20voto

Toby Points 5039

Faites plutôt ce qui suit ?

#ifdef ANOTHER_MACRO
FUNC_MACRO(aVal + offset, bVal);
#else
FUNC_MACRO(aVal, bVal);
#endif

EDIT : Je ne sais pas si la méthode de l'OP est la bonne, mais je ne sais pas non plus si la méthode de l'OP est la bonne. en particulier faux (je pense que d'autres réponses couvrent ce point). Toutefois, la concision et la clarté sont deux aspects jugés importants lors du codage en C.

En tant que tel, je préférerais de loin trouver de meilleurs moyens d'atteindre ce que l'OP semble essayer, en repensant légèrement la situation comme je l'ai proposé ci-dessus. Je suppose que l'OP a peut-être utilisé un exemple trivial, mais je trouve généralement que dans la plupart des situations en C, si quelque chose devient trop complexe ou tente de faire quelque chose que le langage ne semble pas permettre, alors il y a de meilleures façons d'atteindre ce qui est nécessaire.

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