116 votes

Mise en retrait de #defines

Je sais qu' #defines, etc. sont normalement jamais en retrait. Pourquoi?

Je travaille dans un peu de code pour le moment qui a un horrible mélange d' #defines, #ifdefs, #elses, #endifs, etc. Tous ces souvent mélangé avec du normal C du code. Le non-retrait de l' #defines les rend difficiles à lire. Et le mélange de code indenté avec les non-retrait #defines est un cauchemar.

Quel est l'avantage de ne pas l'indentation #defines? Cela fait-il de moi une mauvaise personne si je tiret? N'est-ce pas plus agréable?

#ifdef SDCC
    #if DEBUGGING == 1
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x3DC0
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x7DC0
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #else
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x4000
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x8000
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #endif
#else
    #if DEBUGGING == 1
        #define FLASH_MEMORY_END 0x7DC0
    #else
        #define FLASH_MEMORY_END 0x8000
    #endif
#endif

29voto

tristopia Points 5074

Comme certains l'ont déjà dit, certains Pré-ANSI compilateurs nécessaires le # pour être le premier char sur la ligne, mais ils n'ont pas besoin de directive de préprocesseur pour être attaché à elle, de sorte que l'indentation a été faite de cette façon.

#ifdef SDCC
#  if DEBUGGING == 1
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x3DC0
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x7DC0
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  else
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x4000
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x8000
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  endif
#else
#  if DEBUGGING == 1
#    define FLASH_MEMORY_END 0x7DC0
#  else
#    define FLASH_MEMORY_END 0x8000
#  endif
#endif

Je l'ai souvent vu ce style dans le vieux-Unix-têtes, mais je déteste que la coloration de la syntaxe ne parvient souvent pas à un tel code. J'utilise un très visible de la couleur pour le pré-processeur de la directive, de sorte qu'ils se démarquent (ils sont à un méta-niveau ne devrait donc pas être une partie de l'écoulement normal de code). Vous pouvez même voir que de ne pas la couleur de la séquence de manière utile.

20voto

Jonathan Leffler Points 299946

Concernant l'analyse des directives de préprocesseur, le standard C99 (et la norme C89 avant) étaient claires à propos de la séquence des opérations effectuées logiquement par le compilateur. En particulier, je crois que ça veut dire que ce code:

/* */ # /* */ include /* */ <stdio.h> /* */

est équivalent à:

#include <stdio.h>

Pour le meilleur ou pour le pire, GCC 3.4.4 avec "- std=c89 -pédant' accepte le commentaire-laden ligne, à n'importe quel taux. Je ne dis pas que comme un style pas une seconde (c'est horrible). Je pense juste que c'est possible.

ISO/IEC 9899:1999 section 5.1.1.2 Traduction phases dit:

  1. [Mappage de caractères, y compris trigraphs]

  2. [Épissage en ligne - suppression de la barre oblique inverse newline]

  3. Le fichier source est décomposé en un prétraitement des jetons et des séquences de des espaces blancs (y compris les commentaires). Un fichier source ne doit pas finir dans un partielle de prétraitement de jeton ou d'une partie du commentaire. Chaque commentaire est remplacé par un caractère d'espace. Les caractères de nouvelle ligne sont conservés. Si chaque non vide la séquence de caractères d'espacement autres qu'une nouvelle ligne est conservé ou remplacé par un espace est mise en œuvre définies.

  4. Prétraitement des directives sont exécutées, macro invocations sont élargies, la [...]

L'article 6.10 de Prétraitement des directives dit:

Un prétraitement de la directive consiste en une séquence de prétraitement des jetons qui commence avec un # prétraitement jeton (au début de la phase de traduction de l'4) est le premier caractère dans le fichier source (éventuellement après l'espace blanc ne contenant pas de caractères de nouvelle ligne) ou que suit espace blanc contenant au moins un caractère de nouvelle ligne, et est terminée par la prochaine caractère de nouvelle ligne.

La seule contestation possible est la mise entre parenthèses de l'expression '(au début de la phase de traduction de l'4)", ce qui pourrait signifier que les commentaires avant le hachage doit être absent, car ils ne sont pas remplacés par des espaces jusqu'à la fin de la phase 4.

Comme d'autres l'ont noté, la pré-norme C préprocesseurs ne se comportent pas de manière uniforme dans un certain nombre de façons, et les espaces avant et dans les directives de préprocesseur est l'un des domaines où les différents compilateurs fait différentes choses, y compris de ne pas reconnaître les directives de préprocesseur avec des espaces devant eux.

Il est à noter que l'anti-slash-saut de ligne et le retrait se produit avant que les commentaires sont analysés. Par conséquent, vous ne devriez pas fin // commentaires avec une barre oblique inverse.

5voto

JaredPar Points 333733

Ces jours-ci je crois que c'est surtout un choix de style. Je pense que à un moment donné dans le passé lointain, pas tous les compilateurs pris en charge la notion de mise en retrait du préprocesseur. J'ai fait quelques recherches et a été incapable de sauvegarder cette affirmation. Mais dans tous les cas, il semble que tous les compilateurs modernes soutenir l'idée de la mise en retrait du pré-processeur de macro. Je n'ai pas de copie de la C ou C++ standard bien donc je ne sais pas si c'est le comportement standard ou pas.

Quant à savoir si ou non il est un bon style. Personnellement, j'aime l'idée de les garder tous à gauche. Il vous donne une place de regarder pour eux. Ouais, ça peut devenir agaçant quand il y a de très imbriquées les macros. Mais si vous voulez, vous finirez par la suite avec encore plus étrange à la recherche de code.

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif

3voto

Daniel Fortunov Points 12044

Pour l'exemple que vous avez donné, il peut être approprié d'utiliser l'indentation pour la rendre plus claire, comme vous avez la complexité de la structure d'imbrication des directives.

Personnellement, je pense qu'il est utile de les garder pas en retrait la plupart du temps, parce que ces directives fonctionner séparément du reste de votre code. Des Directives telles que des #ifdef sont traitées par le pré-processeur, avant que le compilateur ne voit jamais votre code, donc un bloc de code après un #ifdef directive ne peut même pas être compilé.

En gardant les directives visuellement séparé du reste de votre code est plus importante lorsqu'elles sont entrecoupées avec le code (plutôt qu'un dédié bloc de directives, comme dans l'exemple que vous donnez).

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