Question Quelles sont les règles d'utilisation d'un trait de soulignement dans un identifiant C ++?


Il est courant en C ++ de nommer les variables membres avec un type de préfixe pour indiquer le fait qu'il s'agit de variables membres plutôt que de variables ou de paramètres locaux. Si vous venez d'un arrière-plan MFC, vous utiliserez probablement m_foo. J'ai aussi vu myFoo parfois.

C # (ou peut-être juste. NET) semble recommander d'utiliser juste un trait de soulignement, comme dans _foo. Est-ce autorisé par le standard C ++?


800
2017-10-23 07:02


origine


Réponses:


Les règles (qui n'ont pas changé en C ++ 11):

  • Réservé dans toute portée, y compris pour une utilisation en tant que macros d'implémentation:
    • identifiants commençant par un trait de soulignement suivi immédiatement d'une lettre majuscule
    • identifiants contenant des traits de soulignement adjacents (ou "double underscore")
  • Réservé dans l'espace de noms global:
    • identifiants commençant par un soulignement
  • En outre, tout dans le std l'espace de noms est réservé. (Vous êtes autorisé à ajouter des spécialisations de modèle, cependant.)

De la norme C ++ 2003:

17.4.3.1.2 Noms globaux [lib.global.names]

Certains ensembles de noms et de signatures de fonctions sont toujours réservés à l'implémentation:

  • Chaque nom qui contient un double trait de soulignement (__) ou commence par un trait de soulignement suivi d'une lettre majuscule (2.11) est réservé à la mise en œuvre pour toute utilisation.
  • Chaque nom qui commence par un trait de soulignement est réservé à l'implémentation pour être utilisé comme nom dans l'espace de noms global.165

165) Ces noms sont également réservés dans l'espace de noms ::std (17.4.3.1).

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

7.1.3 Identifiants réservés

Chaque en-tête déclare ou définit tous les identificateurs énumérés dans son sous-paragraphe associé, et   optionnellement déclare ou définit des identificateurs énumérés dans le sous-paragraphe et les identificateurs futurs de directions de bibliothèque qui lui sont associés et qui sont toujours réservés soit à une utilisation quelconque, soit à une utilisation en tant qu'identifiants d'étendue de fichier.

  • Tous les identifiants commençant par un trait de soulignement et une lettre majuscule ou une autre   Le soulignement est toujours réservé à toute utilisation.
  • Tous les identifiants commençant par un trait de soulignement sont toujours réservés à l'utilisation comme identifiants   avec la portée du fichier dans les espaces de noms ordinaires et de balises.
  • Chaque nom de macro dans l'un des sous-paragraphes suivants (y compris la future bibliothèque   instructions) est réservé à l'utilisation spécifiée si l'un de ses en-têtes associés est inclus;   sauf mention contraire explicite (voir 7.1.4).
  • Tous les identifiants avec liaison externe dans l'un des sous-paragraphes suivants (y compris les   futures directions de bibliothèque) sont toujours réservées pour l'usage comme identifiants avec external   lien.154
  • Chaque identificateur dont la portée est répertoriée dans l'un des sous-paragraphes suivants (y compris   futures instructions de la bibliothèque) est réservé à l'utilisation en tant que nom de macro et en tant qu'identifiant avec   la portée du fichier dans le même espace de noms si l'un de ses en-têtes associés est inclus.

Aucun autre identifiant n'est réservé. Si le programme déclare ou définit un identifiant dans un   contexte dans lequel il est réservé (autre que ce qui est autorisé par le § 7.1.4), ou définit un   identifiant en tant que nom de macro, le comportement est indéfini.

Si le programme supprime (avec #undef) toute définition macro d'un identificateur dans le premier   groupe énuméré ci-dessus, le comportement est indéfini.

154) La liste des identifiants réservés avec liaison externe comprend errno, math_errhandling, setjmp, et va_end.

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

  • Noms commençant par une capitale E suivi d'un chiffre ou d'une majuscule:
    • peut être utilisé pour des noms de code d'erreur supplémentaires.
  • Noms commençant par is ou to suivi d'une lettre minuscule
    • peut être utilisé pour des fonctions de test et de conversion de caractères supplémentaires.
  • Noms commençant par LC_ suivi d'une lettre majuscule
    • peut être utilisé pour des macros supplémentaires spécifiant des attributs régionaux.
  • Les noms de toutes les fonctions mathématiques existantes avec suffixe f ou l sont réservés
    • pour les fonctions correspondantes qui fonctionnent respectivement sur les arguments float et long double.
  • Noms commençant par SIG suivi d'une lettre majuscule sont réservés
    • pour les noms de signaux supplémentaires.
  • Noms commençant par SIG_ suivi d'une lettre majuscule sont réservés
    • pour des actions de signal supplémentaires.
  • Noms commençant par str, mem, ou wcs suivi d'une lettre minuscule sont réservés
    • pour des fonctions de chaîne et de tableau supplémentaires.
  • Noms commençant par PRI ou SCN suivi par une lettre minuscule ou X sont réservés
    • pour les macros de spécification de format supplémentaires
  • Noms qui se terminent par _t sont réservés
    • pour les noms de types supplémentaires.

Bien que l'utilisation de ces noms à vos propres fins en ce moment ne pose pas de problème, ils soulèvent la possibilité d'un conflit avec les futures versions de cette norme.


Personnellement, je ne démarre pas les identifiants avec des traits de soulignement. Nouvel ajout à ma règle: N'utilisez pas de doubles underscores n'importe où, ce qui est facile car j'utilise rarement le underscore.

Après avoir fait des recherches sur cet article, je ne termine plus mes identifiants avec _t comme cela est réservé par le standard POSIX.

La règle à propos de tout identifiant se terminant par _t m'a beaucoup surpris. Je pense que c'est une norme POSIX (pas encore sûre) à la recherche de clarifications et de chapitres et de versets officiels. C'est de la GNU libtool manuel d'utilisation, liste des noms réservés.

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


739
2017-10-23 07:27



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

Règle personnelle

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

Lorsque vous nommez un symbole, vous éviterez les collisions avec les bibliothèques du compilateur / système d'exploitation / standard si vous:

  • ne commence jamais un symbole avec un trait de soulignement
  • Ne nommez jamais un symbole avec deux traits de soulignement consécutifs à l'intérieur.

170
2017-10-23 07:06



De MSDN:

L'utilisation de deux caractères de soulignement séquentiels (__) au début d'un identificateur ou d'un trait de soulignement unique suivi d'une lettre majuscule est réservé aux implémentations C ++ dans toutes les étendues. Vous devez éviter d'utiliser un caractère de soulignement avant suivi d'une lettre minuscule pour les noms avec l'étendue de fichier en raison de conflits possibles avec les identifiants réservés actuels ou futurs.

Cela signifie que vous pouvez utiliser un seul trait de soulignement 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 trouve pas de source originale pour le standard complet en ligne.

Voir également cette question.


28
2017-11-14 20:03



Quant à l'autre partie de la question, il est courant de mettre le trait de soulignement fin du nom de la variable pour ne pas entrer en conflit avec quoi que ce soit d'interne.

Je le fais même à l'intérieur des classes et des espaces de noms parce que je dois seulement me souvenir d'une règle (par rapport à "à la fin du nom dans la portée globale, et le début du nom partout ailleurs").


21
2017-10-23 07:05



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

Les préfixes de soulignement sont communs dans le code C - un seul trait de soulignement signifie "privé", et les doubles traits de soulignement sont généralement réservés à l'usage du compilateur.


2