Question

    

Cette question a déjà une réponse ici:

         

Considérez ceci (horrible, terrible pas bon, très mauvais) structure du code:

#define foo(x) // commented out debugging code

// Misformatted to not obscure the point
if (a)
foo(a);
bar(a);

Je l'ai vu les préprocesseurs de deux compilateurs génèrent des résultats différents sur ce code:

if (a)
bar(a);

et

if (a)
;
bar(a);

De toute évidence, cela est une mauvaise chose pour une base de code portable.

Ma question: Quel est le préprocesseur censé faire avec ça? Elide commentaires d'abord, ou développer des macros d'abord?

Était-ce utile?

La solution

Malheureusement, le originale ANSI C Spécifications exclut spécifiquement les fonctions du préprocesseur de la section 4 ( « Cette spécification ne décrit que le langage C. Il ne prévoit pas non plus la bibliothèque ou le préprocesseur. »).

Le C99 gère ce explicity , bien que. Les commentaires sont remplacés par un seul espace dans la « phase de traduction », ce qui arrive avant l'analyse syntaxique de la directive Prétraitement. (Section 6.10 pour plus de détails).

VC et GNU C Compiler à la fois suivre ce paradigme - autres compilateurs peuvent ne pas être conformes si elles es plus, mais si elle est conforme à C99, vous devriez être en sécurité.

Autres conseils

Comme décrit dans ce decription collé-n-copie des phases de la traduction dans la norme C99, en supprimant les commentaires (ils sont remplacés par un seul espace) se produit dans la phase de traduction 3, tandis que les directives de prétraitement sont manipulés et macros sont développées en phase 4.

Dans la norme C90 (que je n'ai sur papier, donc pas-n copier-coller) ces deux phases se produisent dans le même ordre, bien que la description des phases de traduction est légèrement différente dans certains détails de la norme C99 -. le fait que les commentaires sont supprimés et remplacés par un seul caractère d'espace avant les directives prétraiter sont traitées et les macros développées ne sont pas différentes

Encore une fois, la norme C ++ a ces 2 phases se produisent dans le même ordre.

En ce qui concerne la façon dont doivent être traitées les commentaires 'de //', la norme C99 dit ceci (6.4.9 / 2):

  

Sauf une constante de caractère, une chaîne littérale, ou un commentaire, les caractères //   introduire un commentaire qui inclut tous les caractères multi-octets jusqu'à, mais non compris,   prochain caractère de nouvelle ligne.

Et la norme C de dit (2.7):

  

Les caractères // commencent un commentaire, qui se termine par la prochaine nouvelle ligne   caractère.

Ainsi, votre premier exemple est clairement une erreur de la part de ce traducteur - le caractère « ; » après la foo(a) doit être conservé lorsque la macro foo() est étendue - les caractères de commentaire ne doivent pas faire partie des « contenus » de the foo() macro.

Mais puisque vous êtes confronté à un traducteur buggy, vous pouvez modifier la définition de la macro à:

#define foo(x) /* junk */

pour contourner le bogue.

Cependant (et je suis à la dérive hors sujet ici ...), depuis épissage de ligne (barre oblique inverse juste avant une nouvelle ligne) se produit avant les commentaires sont traités, vous pouvez exécuter en quelque chose comme ce morceau de code méchant:

#define evil( x) printf( "hello "); // hi there, \
                 printf( "%s\n", x); // you!



int main( int argc, char** argv)
{
    evil( "bastard");

    return 0;
}

Ce qui pourrait surprendre celui qui l'a écrite.

Ou mieux encore, essayez ce qui suit, écrit par quelqu'un (! Certainement pas moi) qui aime commentaires boîte de style:

int main( int argc, char** argv)
{
                            //----------------/
    printf( "hello ");      // Hey, what the??/
    printf( "%s\n", "you"); // heck??         /
                            //----------------/
    return 0;
}

Selon que vos paramètres par défaut du compilateur de traitement trigraphes ou non (compilateurs sont supposés, mais depuis trigraphes surpris presque tout le monde qui court à travers eux, certains compilateurs décident de les désactiver par défaut), vous pouvez ou ne pouvez pas obtenir le comportement que vous voulez -. quel que soit le comportement qui est, bien sûr

Selon MSDN , les commentaires sont remplacés avec un espace unique dans la phase de tokenization, qui se produit avant la phase de pré-traitement où macros sont.

Ne mettez jamais // commentaires dans vos macros. Si vous devez mettre des commentaires, utilisez / * * /. De plus, vous avez une erreur dans votre macro:

#define foo(x) do { } while(0) /* junk */

De cette façon, foo est toujours sûr à utiliser. Par exemple:

if (some condition)
    foo(x);

ne sera jamais jeter une erreur de compilation, peu importe si oui ou non foo est défini dans une certaine expression.

#ifdef _TEST_
#define _cerr cerr
#else
#define _cerr / ## / cerr
#endif
  • travaillera sur certains compilateurs (VC ++). Lorsque _TEST_ n'est pas défini,

    _cerr ...

    sera remplacé par la ligne de commentaire

    // cerr ...

Je crois me rappeler que le respect nécessite trois étapes:

  1. bande
  2. macros d'ajout
  3. bande à nouveau

La raison doit faire avec le compilateur étant en mesure d'accepter .i fichiers directement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top