Quelles sont les règles d'utilisation d'un underscore dans un identifiant C++?

il est courant en C++ de nommer des variables membres avec une sorte de préfixe pour indiquer qu'il s'agit de variables membres, plutôt que de variables ou de paramètres locaux. Si vous venez d'un milieu MFC, vous utiliserez probablement m_foo . J'ai aussi vu myFoo de temps en temps.

C# (ou peut-être juste .NET) semble recommander d'utiliser juste un underscore, comme dans _foo . Est-ce permis par le standard c++?

814
demandé sur Taryn 2008-10-23 11:02:06

5 réponses

Les règles (ce qui ne change pas en C++11):

  • réservé dans quelque domaine que ce soit, y compris pour utilisation comme macros de mise en œuvre:
    • identificateurs commençant par un trait de soulignement suivi immédiatement d'une lettre majuscule
    • identificateurs contenant des underscores adjacents (ou" double underscore")
  • réservé dans l'espace de noms global:
    • identificateurs commençant par un underscore
  • en outre, tout dans l'espace de nom std est réservé. (Vous êtes autorisé à ajouter des spécialisations de modèle, bien que.)

à Partir de 2003 de la Norme C++:

17.4.3.1.2 noms mondiaux [lib.mondial.noms]

certains ensembles de noms et de signatures de fonctions sont toujours réservés à la mise en œuvre:

  • chaque nom qui contient un double trait de soulignement ( __ ) ou qui commence par un trait de soulignement suivi d'une lettre majuscule (2.11) est réservé à l'implémentation pour tout usage.
  • chaque nom qui commence par un underscore est réservé à l'implémentation pour utilisation comme nom dans l'espace de noms global. 165

165) tel les noms sont également réservés dans l'Espace-nom ::std (17.4.3.1).

parce que C++ est basé sur la norme C (1.1 / 2, C++03) et C99 est une référence normative (1.2 / 1, C++03) ceux-ci s'appliquent également, à partir de la norme C de 1999:

7.1.3 identificateurs réservés

chaque en-tête déclare ou définit tous les identificateurs énumérés dans sa sous-subdivision associée, et déclare ou définit des identificateurs listé dans ses orientations futures de bibliothèque associées sousclause et identificateurs qui sont toujours réservés soit pour une utilisation quelconque, soit pour une utilisation comme identificateurs de portée de fichier.

  • tous les identificateurs commençant par un trait de soulignement et une lettre en majuscule ou une autre les underscores sont toujours réservés à toute utilisation.
  • tous les identificateurs commençant par un trait de soulignement sont toujours réservés à l'utilisation comme identificateurs avec une portée de fichier à la fois dans l'ordinaire et le nom de la balise espaces.
  • chaque nom de macro dans l'une des sous-classes suivantes (y compris la future bibliothèque mode d'emploi) est réservé à l'usage spécifié si l'un de ses en-têtes associés est inclus; sauf indication contraire explicite (voir 7.1.4).
  • tous les désignations comportant un lien externe dans l'une des sous-classes suivantes (y compris les future library directions) sont toujours réservées à l'usage d'identificateurs externes lien. 154
  • chaque identificateur dont la portée du fichier est énumérée à l'une des subdivisions suivantes (y compris la future library directions) est réservé à l'utilisation comme nom macro et comme Identificateur avec portée du fichier dans l'espace du même nom si l'un de ses en-têtes associés est inclus.

aucun autre identificateur n'est réservé. Si le programme déclare ou définit un identifiant dans contexte dans lequel il est réservé (autres que comme autorisé par 7.1.4), ou définit une réserve identifiant en tant que nom macro, le comportement n'est pas défini.

si le programme supprime (avec #undef ) toute macro définition d'un identifiant dans la première groupe énumérés ci-dessus, le comportement est indéfini.

154) la liste des identificateurs réservés avec lien externe comprend: errno , math_errhandling , setjmp , et va_end .

D'autres restrictions peuvent s'appliquer. Par exemple, la norme POSIX réserve beaucoup d'identificateurs qui sont susceptibles d'apparaître dans le code normal:

  • noms commençant par une majuscule E suivie d'un chiffre ou d'une majuscule:
    • peut être utilisé pour des noms de code d'erreur supplémentaires.
  • qui commence par is ou to suivi d'un lettre minuscule
    • peut être utilisé pour des tests de caractères supplémentaires et des fonctions de conversion.
  • des Noms qui commencent par LC_ suivi d'une lettre majuscule
    • peut être utilisé pour des macros supplémentaires spécifiant des attributs de localisation.
  • les noms de toutes les fonctions mathématiques existantes suffixées de f ou l sont réservés.
    • pour les fonctions correspondantes qui fonctionnent respectivement sur des arguments flottants et des arguments doubles longs.
  • les noms commençant par SIG suivis d'une lettre majuscule sont réservés
    • pour les noms de signaux supplémentaires.
  • les noms commençant par SIG_ suivis d'une lettre majuscule sont réservés
    • pour signal d'actions.
  • les noms commençant par str , mem , ou wcs suivis d'une lettre minuscule sont réservés
    • pour des fonctions supplémentaires de chaîne et de tableau.
  • les noms commençant par PRI ou SCN suivis de toute lettre minuscule ou X sont réservés
    • pour plus d'spécificateur de format macros
  • Les Noms qui se terminent par _t sont réservés
    • pour les noms de type supplémentaires.

bien que l'utilisation de ces noms à vos propres fins dès maintenant pourrait ne pas causer de problème, ils soulèvent la possibilité d'un conflit avec les versions futures de cette norme.


personnellement, je ne commence pas les identifiants par des caractères de soulignement. Nouvel ajout à ma règle: N'utilisez pas de double underscores n'importe où, ce qui est facile car j'utilise rarement underscore.

après avoir fait des recherches sur cet article Je ne termine plus mes identificateurs avec _t comme cela est réservé par le standard POSIX.

la règle concernant tout identificateur se terminant par _t m'a beaucoup surpris. Je pense que C'est une norme POSIX (pas encore sûr) à la recherche de clarification et de chapitre officiel et le verset. Il s'agit du GNU libtool manual , qui répertorie les noms réservés.

CesarB fourni le lien suivant vers le POSIX 2004 symboles et notes réservés " que de nombreux autres préfixes et suffixes réservés ... peut être trouvé là-bas". Le POSIX 2008 les symboles réservés sont définis ici. Les restrictions sont un peu plus nuancées que celles ci-dessus.

746
répondu 23 revs, 12 users 36%Roger Pate 2018-02-06 12:04:38

les règles pour éviter la collision des noms sont à la fois dans la norme c++ (voir le livre de Stroustrup) et mentionnés par C++ gurus (Sutter, etc.).

règle personnelle

parce que je ne voulais pas traiter des cas, et que je voulais une règle simple, j'ai conçu un personnel un qui est à la fois simple et correcte:

En nommant un symbole, vous éviterez la collision avec les bibliothèques compilatrices/OS/standard si vous:

  • ne commencez jamais un symbole avec un trait de soulignement
  • ne jamais nommer un symbole avec deux underscores consécutifs à l'intérieur.

bien sûr, mettre votre code dans un espace de noms unique aide à éviter la collision, aussi (mais ne protégera pas contre les macros maléfiques)

quelques exemples

(j'utilise des macros parce qu'elles sont plus polluantes pour les symboles c / c++ , mais cela pourrait être n'importe quoi de nom de variable à nom de classe)

#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT

extraits de C++0x draft

du n3242.pdf fichier (j'attend le dernier standard de texte similaire):

17.6.3.3.2 noms mondiaux [mondial.noms]

certains ensembles de noms et de signatures de fonctions sont toujours réservés à la mise en œuvre:

- chaque nom qui contient un double underscore _ _ ou qui commence par un underscore suivi d'une lettre majuscule (2.12) est réservé à l'implémentation pour tout usage.

- chaque nom qui commence par un underscore est réservé à l'implémentation pour utilisation comme nom dans l'espace de noms global.

mais aussi:

17.6.3.3.5 suffixes littéraux définis par L'utilisateur [usrlit.suffixe]

Les identificateurs de suffixe littéral

qui ne commencent pas par un underscore sont réservés pour une future standardisation.

cette dernière clause est déroutante, à moins que vous ne considériez qu'un nom commençant par un underscore et suivi d'une lettre en minuscules serait Ok si n'était pas défini dans l'espace de noms global...

172
répondu paercebal 2011-06-27 20:32:18

de MSDN :

L'utilisation de deux caractères de soulignement séquentiels ( __ ) au début d'un identificateur, ou d'un seul trait de soulignement suivi d'une lettre majuscule, est réservée aux implémentations C++ dans tous les champs d'application. Vous devriez éviter d'utiliser un underscore suivi d'une lettre en minuscules pour les noms ayant une portée de fichier en raison de conflits possibles avec les identificateurs réservés actuels ou futurs.

cela signifie que vous pouvez utiliser un seul underscore comme préfixe de variable membre, à condition qu'il soit suivi d'une lettre minuscule.

ceci est apparemment tiré de la section 17.4.3.1.2 de la norme C++, mais je ne peux pas trouver une source originale pour la norme complète en ligne.

Voir aussi cette question .

27
répondu Roger Lipscombe 2017-05-23 12:02:50

quant à l'autre partie de la question, il est courant de mettre le soulignement au fin du nom de la variable pour ne pas entrer en conflit avec quelque chose d'interne.

je le fais même à l'intérieur des classes et des namespaces parce que je n'ai plus qu'une règle à me rappeler (comparée à "à la fin du nom dans la portée globale, et au début du nom partout ailleurs").

21
répondu Max Lybbert 2017-09-01 16:10:18

Oui, les soulignements peuvent être utilisés n'importe où dans un identificateur. Je crois que les règles sont: tout a-z, A-Z, _ dans le premier caractère et ceux + 0-9 pour les caractères suivants.

les préfixes de soulignement sont courants dans le code C -- Un seul soulignement signifie "privé", et les soulignements doubles sont habituellement réservés à l'usage du compilateur.

2
répondu John Millikin 2008-10-23 07:05:58