Question

En C ++, il est courant de nommer les variables membres avec une sorte de préfixe afin d'indiquer le fait qu'elles sont des variables membres, plutôt que des variables ou des paramètres locaux. Si vous venez d’un milieu MFC, vous utiliserez probablement m_foo . J'ai aussi vu myFoo à l'occasion.

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

Était-ce utile?

La solution

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

  • Réservé dans toutes les portées, y compris pour être utilisé comme macros implémentation :
    • identificateurs commençant par un trait de soulignement suivi immédiatement d'une lettre majuscule
    • identificateurs contenant des traits de soulignement adjacents (ou "soulignement double")
  • Réservé dans l'espace de noms global:
    • identificateurs commençant par un trait de soulignement
  • De même, tout ce qui se trouve dans l'espace de noms std est réservé. (Vous êtes cependant autorisé à ajouter des spécialisations de modèles.)

À partir 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 à la mise en oeuvre:

     
      
  • Chaque nom contenant un double trait de soulignement ( __ ) ou commençant par un trait de soulignement suivi d'une lettre majuscule (2.11) est réservé à la mise en oeuvre pour toute utilisation.
  •   
  • Chaque nom commençant par un trait de soulignement est réservé à l'implémentation pour pouvoir ê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).

Etant donné que C ++ est basé sur le standard 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 du standard 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 son sous-paragraphe associé, et   déclare ou définit facultativement les identifiants répertoriés dans le sous-paragraphe relatif aux instructions de la future bibliothèque, ainsi que les identifiants toujours réservés à une utilisation ou à une utilisation en tant qu'identificateurs d'étendue de fichier.

     
      
  • Tous les identificateurs commençant par un trait de soulignement et une lettre majuscule ou une autre   les traits de soulignement sont toujours réservés pour toute utilisation.
  •   
  • Tous les identifiants commençant par un trait de soulignement sont toujours réservés à une utilisation en tant qu'identificateurs   avec la portée du fichier à la fois dans les espaces de nom ordinaire et de nom de balise.
  •   
  • Chaque nom de macro dans l’un des sous-paragraphes suivants (y compris la future bibliothèque   directions) est réservé pour une utilisation spécifiée si l’un des en-têtes associés est inclus;   sauf indication contraire (voir 7.1.4).
  •   
  • Tous les identifiants avec une liaison externe dans l’un des sous-paragraphes suivants (y compris le   futures directions de la bibliothèque) sont toujours réservés à l’utilisation en tant qu’identifiants avec   liaison. 154
  •   
  • Chaque identifiant dont l’étendue du fichier est répertoriée dans l’un des sous-paragraphes suivants (y compris le   futures directions de la bibliothèque) est réservé à l’utilisation en tant que nom de macro et en tant qu’identifiant avec   Portée du fichier dans le même espace de nom si l'un des 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 une   contexte dans lequel il est réservé (autre que celui autorisé par 7.1.4), ou définit un   identifiant en tant que nom de macro, le comportement n'est pas défini.

     

Si le programme supprime (avec #undef ) toute définition de macro d'un identifiant dans la première   groupe mentionné ci-dessus, le comportement n'est pas défini.

     

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

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

  • Les noms commençant par un majuscule suivi d'un chiffre ou d'une lettre majuscule:
    • peut être utilisé pour d'autres noms de code d'erreur.
  • Les noms commençant par est ou en suivi d'une lettre minuscule
    • peut être utilisé pour des tests de caractères et des fonctions de conversion supplémentaires.
  • Noms commençant par LC _ suivi d'une lettre majuscule
    • peut être utilisé pour des macros supplémentaires spécifiant des attributs de paramètres régionaux.
  • Les noms de toutes les fonctions mathématiques existantes portant le suffixe f ou l sont réservés.
    • pour les fonctions correspondantes qui fonctionnent respectivement sur les arguments float et long double.
  • 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 _ suivi d'une lettre majuscule sont réservés.
    • pour des actions de signal supplémentaires.
  • Les 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.
  • Les noms commençant par PRI ou SCN suivi d'une lettre minuscule ou X sont réservés.
    • pour les macros de spécificateur de format supplémentaires
  • Les noms qui se terminent par _t sont réservés.
    • pour les noms de types supplémentaires.

Bien que l'utilisation de ces noms pour vos propres besoins actuels ne pose aucun problème, ils peuvent toutefois entraîner des conflits avec les versions futures de cette norme.

Personnellement, je ne commence pas les identifiants avec des traits de soulignement. Nouvel ajout à ma règle: n'utilisez pas de double trait de soulignement n'importe où, ce qui est facile, car j'utilise rarement le trait de soulignement.

Après avoir effectué 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 concernant tout identifiant se terminant par _t m'a beaucoup surpris. Je pense que c’est un standard POSIX (pas encore sûr) qui cherche une clarification, un chapitre et un vers officiels. Cela provient du Manuel de GNU libtool , qui répertorie les noms réservés. .

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

Autres conseils

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 de cas et que je voulais une règle simple, j’en ai conçu une personnelle simple et correcte:

En nommant un symbole, vous éviterez les conflits avec les bibliothèques du compilateur / OS / standard si vous:

  • ne commencez jamais un symbole avec un trait de soulignement
  • ne nommez jamais un symbole contenant deux traits de soulignement consécutifs.

Bien sûr, placer votre code dans un espace de noms unique permet également d'éviter les conflits (sans vous protéger contre les macros diaboliques)

Quelques exemples

(J'utilise des macros car ce sont les symboles C / C ++ les plus polluants, mais cela peut aller du nom de la variable au nom de la classe)

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

Extraits du brouillon C ++ 0x

Extrait du n3242.pdf fichier (je m'attends à ce que le texte standard final soit similaire):

  

17.6.3.3.2 Noms globaux [noms globaux]

     

Certains ensembles de noms et de signatures de fonctions sont toujours réservés à la mise en oeuvre:

     

- Chaque nom contenant un double trait de soulignement _ _ ou commençant par un trait de soulignement suivi d'une lettre majuscule (2.12) est réservé à la mise en oeuvre pour toute utilisation.

     

- Chaque nom commençant par un trait de soulignement est réservé à l'implémentation pour pouvoir être utilisé comme nom dans l'espace de noms global.

Mais aussi:

  

17.6.3.3.5 Suffixes littéraux définis par l'utilisateur [usrlit.suffix]

     

Les identificateurs de suffixe littéral qui ne commencent pas par un trait de soulignement sont réservés pour la normalisation future.

Cette dernière clause est source de confusion, sauf si vous considérez qu'un nom commençant par un trait de soulignement et suivi d'une lettre minuscule serait correct si non n'est pas défini dans l'espace de nom global ...

De MSDN :

  

L'utilisation de deux caractères de soulignement (__) séquentiels au début d'un identificateur, ou d'un seul soulignement avant suivi d'une lettre majuscule, est réservée aux implémentations C ++ dans toutes les portées. Vous devez éviter d'utiliser un trait de soulignement suivit d'une lettre minuscule pour les noms avec la portée du fichier en raison de conflits éventuels avec les identificateurs réservés actuels ou futurs.

Cela signifie que vous pouvez utiliser un simple 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 la norme complète en ligne.

Voir aussi cette question .

Pour ce qui est de l’autre partie de la question, il est courant de mettre le trait de soulignement à la fin du nom de la variable afin de ne pas entrer en conflit avec des éléments internes.

Je le fais même à l'intérieur des classes et des espaces de noms car je n'ai alors plus qu'à mémoriser une règle (comparé à "à la fin du nom dans la portée globale et au début du nom partout ailleurs").

Oui, les traits de soulignement peuvent être utilisés n’importe où dans un identifiant. Je crois que les règles sont les suivantes: 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 soulignement simple signifie "privé", et les soulignements doubles sont généralement réservés à l'usage du compilateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top