Pourquoi les gens utilisent-ils autant __ (double trait de soulignement) en C ++

93

J'étais en train de parcourir du code C ++ open source et j'ai remarqué beaucoup de doubles sous-scores utilisés dans le code, principalement au début des noms de variables.

return __CYGWIN__;

Vous vous demandez simplement s'il y a une raison à cela, ou est-ce juste des gens qui codent des styles? Je pense que cela rend la lecture difficile.

Nathan W
la source
2
Pourquoi difficile à lire? Il est principalement conçu comme un délimiteur, tout comme les citations. Si je me souviens bien, il est principalement utilisé pour les constantes intégrées.
Matthew Scharley
1
Non, ce n'est pas un délimiteur. Les traits de soulignement sont utilisés pour distinguer les noms réservés pour l'implémentation des noms que le code source des utilisateurs peut utiliser. Les utilisateurs peuvent faire #define FOO 1mais ils ne doivent pas le faire #define __FOO__ 1et par conséquent, l'implémentation est libre d'utiliser le nom __FOO__pour ses propres macros, variables, fonctions, etc.
Jonathan Wakely
Je pense que Matthew voulait dire que c'est stylistiquement / visuellement un délimiteur, pas fonctionnellement. Ce qui est une hypothèse intéressante, mais incorrecte compte tenu de ce que j'ai lu précédemment et de la réponse de Jonathan.
JMI MADISON

Réponses:

127

De la programmation en C ++, règles et recommandations :

L'utilisation de deux traits de soulignement (`__ ') dans les identifiants est réservée à l'usage interne du compilateur selon la norme ANSI-C.

Les traits de soulignement (`_ ') sont souvent utilisés dans les noms de fonctions de bibliothèque (comme" _main "et" _exit "). Afin d'éviter les collisions, ne commencez pas un identificateur par un trait de soulignement.

maccullt
la source
1
Ce guide semble avoir été écrit avant d' namespaceêtre présenté.
cz
il provenait également du collège impérial de Londres et non du standard C ++; ce peut être une bonne suggestion.
stucash
1
Les espaces de noms @cz ne sont pas pertinents. Un en-tête système pourrait définir un nom de macro commençant par un trait de soulignement, par exemple _main.
martinkunev
49

À moins qu'ils ne sentent qu'ils font «partie de l'implémentation», c'est-à-dire des bibliothèques standard, ils ne devraient pas le faire.

Les règles sont assez spécifiques et sont un peu plus détaillées que certains autres l'ont suggéré.

Tous les identifiants contenant un double trait de soulignement ou commençant par un trait de soulignement suivi d'une lettre majuscule sont réservés à l'utilisation de l'implémentation dans toutes les portées, c'est-à-dire qu'ils peuvent être utilisés pour des macros.

De plus, tous les autres identifiants qui commencent par un trait de soulignement (c'est-à-dire non suivi d'un autre trait de soulignement ou d'une lettre majuscule) sont réservés pour l'implémentation au niveau global. Cela signifie que vous pouvez utiliser ces identificateurs dans vos propres espaces de noms ou dans des définitions de classe.

C'est pourquoi Microsoft utilise des noms de fonctions avec un trait de soulignement en tête et le tout en minuscules pour bon nombre de leurs fonctions de bibliothèque d'exécution principales qui ne font pas partie de la norme C ++. Ces noms de fonction sont garantis de ne pas entrer en conflit avec les fonctions C ++ standard ou les fonctions de code utilisateur.

CB Bailey
la source
1
En C ++, je ne vois que [lex.name] et pour les noms globaux [global.names]. Pouvez-vous donner des références? merci
a.lasram
36

Selon la norme C ++, les identificateurs commençant par un trait de soulignement sont réservés aux bibliothèques. Les identificateurs commençant par deux traits de soulignement sont réservés aux fournisseurs de compilateurs.

James Curran
la source
18
Plus que cela: les identifiants contenant un double trait de soulignement n'importe où sont réservés. 17.4.3.1.2
Steve Jessop
En C ++, je ne vois que [lex.name] et pour les noms globaux [global.names]. Pouvez-vous donner des références? merci
a.lasram
10

Les commentaires précédents sont corrects. __Symbol__est généralement un jeton magique fourni par votre fournisseur de compilateur (ou préprocesseur) utile. Les plus utilisés sont peut-être __FILE__et __LINE__, qui sont développés par le préprocesseur C pour indiquer le nom de fichier et le numéro de ligne actuels. C'est pratique lorsque vous souhaitez enregistrer une sorte d'échec d'assertion de programme, y compris l'emplacement textuel de l'erreur.

tourbière
la source
8

C'est quelque chose que vous n'êtes pas censé faire dans un code «normal». Cela garantit que les compilateurs et les bibliothèques système peuvent définir des symboles qui n'entreront pas en conflit avec les vôtres.

Menkboy
la source
4

Les doubles traits de soulignement sont réservés à l'implémentation

La réponse la plus votée cite la programmation en C ++: règles et recommandations :

"L'utilisation de deux traits de soulignement (` __ ') dans les identificateurs est réservée à l'usage interne du compilateur selon la norme ANSI-C. "

Cependant, après avoir lu quelques C ++ et les normes C, je ne pouvais trouver aucune mention de underscores étant limité à seulement une utilisation interne du compilateur. Les normes sont plus générales, réservant un double soulignement pour la mise en œuvre .

C ++

C ++ (version de travail actuelle, consulté le 2019-5-26) indique lex.name:

  • Chaque identifiant contenant un double trait de soulignement __ ou commençant par un trait de soulignement suivi d'une lettre majuscule est réservé à l'implémentation pour toute utilisation.
  • Chaque identificateur qui commence par un trait de soulignement est réservé à l'implémentation pour être utilisé comme nom dans l'espace de noms global.

C

Bien que cette question soit spécifique au C ++, j'ai cité des sections pertinentes des normes C 99 et 17:

C99 section 7.1.3

  • Tous les identifiants qui commencent par un trait de soulignement et une lettre majuscule ou un autre trait de soulignement sont toujours réservés pour toute utilisation.
  • Tous les identificateurs qui commencent par un trait de soulignement sont toujours réservés pour être utilisés comme identificateurs avec une portée de fichier dans les espaces de nom ordinaire et de balise.

C17 dit la même chose que C99.

Quelle est la mise en œuvre ?

Pour C / C ++, l' implémentation fait généralement référence aux ressources d'ensemble nécessaires pour produire un exécutable à partir de fichiers source utilisateur. Ceci comprend:

  • préprocesseur
  • compilateur
  • éditeur de liens
  • bibliothèque standard

Exemples d'implémentations

Il existe un certain nombre d'implémentations C ++ différentes mentionnées sur Wikipedia . (pas de lien d'ancrage, ctrl + f "implémentation")

Voici un exemple d'implémentation C / C ++ de Digital Mars réservant certains mots-clés à une de leurs fonctionnalités.

RemarquableBucket
la source
3

En plus des bibliothèques sur lesquelles beaucoup d'autres personnes ont répondu, certaines personnes nomment également des macros ou des valeurs #define à utiliser avec le préprocesseur. Cela faciliterait le travail et aurait permis de contourner des bogues dans les anciens compilateurs.

Comme d'autres l'ont mentionné, il permet d'éviter la collision de noms et de délimiter entre les variables de bibliothèque et les vôtres.

Sqeaky
la source