Peut-on écrire une macro sur plusieurs lignes sans la barre oblique inverse à la fin?

J’ai vu quelques exemples dans le manuel CPP où nous pouvons écrire le corps de macros dans plusieurs lignes sans la barre oblique inverse.

#define strange(file) fprintf (file, "%s %d", ... strange(stderr) p, 35) 

sortie:

 fprintf (stderr, "%s %d", p, 35) 

S’agit-il de cas particuliers tels que des directives à l’intérieur de macros d’arguments ou est-ce autorisé uniquement pour #define?

Pour les directives include, il faut toujours déclarer sur une ligne si je ne me trompe pas.

Modifier:

De https://gcc.gnu.org/onlinedocs/cpp/Directives-Within-Macro-Arguments.html

3.9 Directives dans les arguments de macro

Il est parfois pratique d’utiliser des directives de préprocesseur dans les arguments d’une macro . Les normes C et C ++ déclarent que le comportement dans ces cas n’est pas défini. GNU CPP traite les directives arbitraires contenues dans les macro-arguments exactement de la même manière qu’il aurait traité la directive si la macro invocation de type fonction n’était pas présente.

Si, dans une invocation de macro, cette macro est redéfinie, la nouvelle définition prend effet à temps pour le pré-développement des arguments, mais la définition d’origine est toujours utilisée pour le remplacement des arguments. Voici un exemple pathologique:

  #define f(x) xx f (1 #undef f #define f 2 f) 

qui s’étend à

  1 2 1 2 

avec la sémantique décrite ci-dessus.

L’exemple est sur plusieurs lignes.

Définitions de macros multiligne sans backslash-newline

Les commentaires étant remplacés par des espaces dans la phase de traduction 3:

  1. Le fichier source est décomposé en jetons de pré-traitement 7) 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 ni par un commentaire partiel. Chaque commentaire est remplacé par un espace. Les caractères de nouvelle ligne sont conservés. Que chaque séquence non vide de caractères d’espace blanc autre que nouvelle ligne soit conservée ou remplacée par un caractère d’espace est définie par l’implémentation.

et le préprocesseur s’exécute en phase 4:

  1. Les directives de prétraitement sont exécutées, les invocations de macros développées et les expressions d’opérateur unaire _Pragma exécutées. Si une séquence de caractères correspondant à la syntaxe d’un nom de caractère universel est générée par concaténation de jetons (6.10.3.3), le comportement est indéfini. Une directive de prétraitement #include entraîne le traitement récursif de l’en-tête nommé ou du fichier source de la phase 1 à la phase 4. Toutes les directives de prétraitement sont ensuite supprimées.

il est possible, mais absurde, d’écrire une macro multiligne comme ceci:

 #include  #define possible_but_absurd(a, b) /* comments */ printf("are translated"); /* in phase 3 */ printf(" before phase %d", a); /* (the preprocessor) */ printf(" is run (%s)\n", b); /* but why abuse the system? */ int main(void) { printf("%s %s", "Macros can be continued without backslashes", "because comments\n"); possible_but_absurd(4, "ISO/IEC 9899:2011,\nSection 5.1.1.2" " Translation phases"); return 0; } 

qui, lorsqu’il est exécuté, indique:

 Macros can be continued without backslashes because comments are translated before phase 4 is run (ISO/IEC 9899:2011, Section 5.1.1.2 Translation phases) 

Backslash-newline dans les définitions de macro

Les phases de traduction 1 et 2 sont également quelque peu pertinentes:

  1. Les caractères multi-octets du fichier source physique sont mappés, de manière définie par l’implémentation, au jeu de caractères source (en introduisant des caractères de nouvelle ligne pour les indicateurs de fin de ligne) si nécessaire. Les séquences de sortinggraphes sont remplacées par des représentations internes à un caractère correspondantes.

Le remplacement du sortinggraphe est nominalement pertinent parce que ??/ est le sortinggraphe d’une barre oblique inverse.

  1. Chaque occurrence d’un caractère barre oblique inversée ( \ ) immédiatement suivie d’un caractère de nouvelle ligne est supprimée, ce qui permet d’épisser les lignes source physiques pour former des lignes source logiques. Seule la dernière barre oblique inverse d’une ligne source physique est éligible pour faire partie d’une telle épissure. Un fichier source qui n’est pas vide doit se terminer par un caractère de nouvelle ligne, qui ne doit pas être immédiatement précédé d’un caractère de barre oblique inverse avant qu’une telle fusion ne soit effectuée.

Cela vous indique que, au moment de l’exécution de la phase 4 (préprocesseur), les définitions de macros se trouvent sur une seule ligne (logique) – les combinaisons de fin de barre oblique inverse et de nouvelle ligne ont été supprimées.

La norme note que les phases sont “comme si” – le comportement du compilateur doit être comme s’il passait par des phases séparées, mais de nombreuses implémentations ne les séparent pas formellement de manière complète.


Eviter l’extension GCC

L’exemple développé (citation du manuel GCC) a l’invocation répartie sur plusieurs lignes, mais la définition est ssortingctement sur une ligne. (Ce n’est pas une extension de GCC, mais un comportement complètement standard.)

Notez que si vous êtes sain d’esprit à distance, vous ignorerez la possibilité de placer des directives de pré-traitement dans l’appel d’une macro ( #undef et #define dans l’exemple). C’est une extension de GCC et totalement inutilisable. La norme dit que le comportement n’est pas défini.

Annexe J.2 Comportement non défini

  • Il existe dans la liste des macro-arguments des séquences de jetons de prétraitement qui agiraient sinon comme des directives de prétraitement (6.10.3).

Non ce n’est pas possible. Les épissures de ligne sont traitées avant chaque ligne pour être interprétées comme une ligne de texte de code ou une directive de pré-traitement et, à l’étape 4 du préprocesseur (l’algorithme de prétraitement effectif) n’arrivent pas d’épissage de ligne, car elles ont été éliminées auparavant.

 #define strange(file) fprintf (file, "%s %d", 

Votre définition est interprétée comme une macro de fonction dans laquelle le préprocesseur remplace l’appel strange(stderr) par fprintf (stderr, "%s %d", ,. Le préprocesseur n’a aucune connaissance de la syntaxe et de la sémantique C, c’est un autre langage, non turing. -Achevée.

Non tu ne peux pas. Vous devez utiliser une barre oblique inverse en tant que caractère d’échappement de continuation de ligne pour les macros de préprocesseur multiligne.