En retrait #defines

Je sais que #define s, etc. ne sont normalement jamais en retrait. Pourquoi?

Je travaille actuellement sur un code qui contient un mélange horrible de #define s, #ifdef s, #else s, #endif s, etc. Tous ces éléments sont souvent mélangés avec du code C normal. La non-indentation des #define s les rend difficiles à lire. Et le mélange de code indenté avec #define s non indenté est un cauchemar.

Quel est l’avantage de ne pas indenter #define s? Est-ce que ça fait de moi une mauvaise personne si je les indiens? N’est-ce pas mieux?

 #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 

Le préprocesseur pré-ANSI C ne permettait pas d’espace entre le début d’une ligne et le caractère “#”; le premier “#” doit toujours être placé dans la première colonne.

Les compilateurs pré-ANSI C sont inexistants ces jours-ci. Utilisez le style que vous préférez (espace avant “#” ou espace entre “#” et l’identifiant).

http://www.delorie.com/gnu/docs/gcc/cpp_48.html

Comme certains l’ont déjà dit, certains compilateurs pré-ANSI exigeaient que # soit le premier caractère de la ligne, mais ils ne nécessitaient pas de directive de préprocesseur, de sorte que l’indentation était 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 

J’ai souvent vu ce style dans les anciens en-têtes Unix, mais je le déteste car la coloration de la syntaxe échoue souvent avec ce code. J’utilise une couleur très visible pour les directives de préprocesseur afin qu’elles se distinguent (elles se situent à un niveau méta et ne devraient donc pas faire partie du stream normal du code). Vous pouvez même voir que SO ne colore pas la séquence de manière utile.

En ce qui concerne l’parsing des directives de préprocesseur, le standard C99 (et le standard C89 avant lui) étaient clairs sur la séquence d’opérations exécutées de manière logique par le compilateur. En particulier, je pense que cela signifie que ce code:

 /* */ # /* */ include /* */  /* */ 

est équivalent à:

 #include  

Pour le meilleur ou pour le pire, GCC 3.4.4 avec «-std = c89 -pedantic» accepte la ligne chargée de commentaires, en tout cas. Je ne préconise pas cela comme un style – pas pour une seconde (c’est horrible). Je pense juste que c’est possible.

ISO / IEC 9899: 1999 section 5.1.1.2 Les phases de traduction sont les suivantes:

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

  2. [Épissage de ligne – suppression de la barre oblique inverse]

  3. Le fichier source est décomposé en jetons de prétraitement et en séquences de caractères d’espace blanc (y compris les commentaires). Un fichier source ne doit pas se terminer par un jeton de prétraitement partiel ou par un commentaire partiel. Chaque commentaire est remplacé par un caractère d’espace. Les caractères de nouvelle ligne sont conservés. Si chaque séquence non vide d’espaces blancs autres que les nouvelles lignes est conservée ou remplacée par un caractère d’espacement, elle est définie par l’implémentation.

  4. Les directives de prétraitement sont exécutées, les invocations de macro sont développées, […]

Section 6.10 Les directives de prétraitement indiquent:

Une directive de prétraitement consiste en une séquence de jetons de prétraitement qui commence par un jeton de prétraitement # (au début de la phase de traduction 4) soit le premier caractère du fichier source (éventuellement après un espace blanc ne contenant pas de caractères de nouvelle ligne) ou suit un espace blanc contenant au moins un caractère de nouvelle ligne et se termine par le caractère de nouvelle ligne suivant.

Le seul conflit possible est l’expression entre parenthèses «(au début de la phase de traduction 4)», ce qui pourrait signifier que les commentaires avant le hachage doivent être absents car ils ne sont pas remplacés par des espaces jusqu’à la fin de la phase 4.

Comme d’autres l’ont noté, les préprocesseurs C pré-standard ne se comportaient pas de différentes manières et les espaces avant et dans les directives du préprocesseur étaient l’un des domaines où différents compilateurs faisaient des choses différentes, notamment ne pas reconnaître les directives du préprocesseur .

Il convient de noter que le retrait de barre oblique inverse-ligne se produit avant que les commentaires ne soient analysés. Par conséquent, vous ne devez pas terminer // commentaires avec une barre oblique inverse.

Je ne sais pas pourquoi ce n’est pas plus commun. Il y a certainement des moments où j’aime indenter des directives de préprocesseur.

Une chose qui continue à me perturber (et me convainc parfois à ne plus essayer) est que la plupart des éditeurs / éditeurs / directeurs de publication lancent la directive à la colonne 1 à la moindre provocation. Ce qui est ennuyeux comme l’enfer.

Ces jours-ci, je crois que c’est principalement un choix de style. Je pense qu’à un moment donné dans le passé, tous les compilateurs ne supportaient pas la notion d’indentation des définitions du préprocesseur. J’ai fait des recherches et j’ai été incapable de soutenir cette affirmation. Mais dans tous les cas, il semble que tous les compilateurs modernes supportent l’idée de mettre en retrait la macro pré-processeur. Je n’ai pas de copie du standard C ou C ++, donc je ne sais pas s’il s’agit d’un comportement standard ou non.

Quant à savoir si c’est bon ou non. Personnellement, j’aime l’idée de les garder tous à gauche. Cela vous donne un endroit cohérent pour les chercher. Oui, ça peut être agaçant quand il y a des macros très nestedes. Mais si vous les indentez, vous finirez par avoir un code encore plus étrange.

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

Pour l’exemple que vous avez donné, il peut être approprié d’utiliser l’indentation pour le rendre plus clair, car vous avez une structure complexe de directives nestedes.

Personnellement, je pense qu’il est utile de ne pas les mettre en retrait la plupart du temps, car ces directives fonctionnent séparément du rest de votre code. Les directives telles que #ifdef sont gérées par le préprocesseur, avant que le compilateur ne voit votre code, donc un bloc de code après une directive #ifdef ne peut même pas être compilé .

Garder les directives visuellement séparées du rest de votre code est plus important quand elles sont intercalées avec du code (plutôt qu’un bloc de directives dédié, comme dans l’exemple que vous donnez).

Je travaille actuellement sur un code qui contient un mélange horrible de #defines, #ifdefs, #elses, #endifs, #etc. Tous ces éléments se sont souvent mélangés au code C normal. La non-indentation des #defines les rend difficiles à lire. Et le mélange de code indenté avec #defines non indenté est un cauchemar.

Une solution commune consiste à commenter les directives, afin que vous sachiez facilement à quoi elles renvoient:

 #ifdef FOO /* a lot of code */ #endif /* FOO */ #ifndef FOO /* a lot of code */ #endif /* not FOO */