Lookup and name spaces
Lorsqu'un identifiant est rencontré dans un programme C, une recherche est effectuée pour localiser la déclaration qui a introduit cet identifiant et qui est actuellement dans la portée . Le C permet à plusieurs déclarations du même identifiant d'être simultanément dans la portée si ces identifiants appartiennent à différentes catégories, appelées espaces de noms :
|
4)
Espace de noms des attributs globaux :
jetons d'attribut
définis par la norme ou préfixes d'attributs définis par l'implémentation.
5)
Noms d'attributs non standard : noms d'attributs suivant les préfixes d'attributs. Chaque préfixe d'attribut possède un espace de noms distinct pour les attributs définis par l'implémentation qu'il introduit.
|
(depuis C23) |
Au moment de la recherche, l'espace de noms d'un identifiant est déterminé par la manière dont il est utilisé :
|
4)
L'identifiant qui apparaît directement dans un spécificateur d'attribut (
[
[
...
]
]
) est recherché dans l'espace de noms global des attributs.
5)
L'identifiant qui suit le jeton
::
suivant un préfixe d'attribut est recherché dans l'espace de noms introduit par le préfixe d'attribut.
|
(depuis C23) |
Table des matières |
Notes
Les noms des macros ne font partie d'aucun espace de noms car ils sont remplacés par le préprocesseur avant l'analyse sémantique.
Il est courant d'injecter les noms de struct/union/enum dans l'espace de noms des identifiants ordinaires en utilisant une déclaration typedef :
struct A { }; // introduit le nom A dans l'espace de noms des balises typedef struct A A; // d'abord, la recherche de A après "struct" en trouve un dans l'espace de noms des balises // puis introduit le nom A dans l'espace de noms ordinaire struct A* p; // OK, ce A est recherché dans l'espace de noms des balises A* q; // OK, ce A est recherché dans l'espace de noms ordinaire
Un exemple bien connu du même identifiant utilisé dans deux espaces de noms est l'identifiant
stat
de l'en-tête POSIX
sys/stat.h
. Il
désigne une fonction
lorsqu'il est utilisé comme identifiant ordinaire et
indique une structure
lorsqu'il est utilisé comme tag.
Contrairement à C++, les constantes d'énumération ne sont pas des membres de structure, et leur espace de noms est l'espace de noms des identifiants ordinaires, et puisqu'il n'y a pas de portée de structure en C, leur portée est la portée dans laquelle la déclaration de structure apparaît :
struct tagged_union { enum {INT, FLOAT, STRING} type; union { int integer; float floating_point; char *string; }; } tu; tu.type = INT; // Correct en C, erreur en C++
|
Si un attribut standard, un préfixe d'attribut ou un nom d'attribut non standard n'est pas pris en charge, l'attribut non valide lui-même est ignoré sans provoquer d'erreur. |
(depuis C23) |
Exemple
void foo (void) { return; } // espace de noms ordinaire, portée fichier struct foo { // espace de noms d'étiquette, portée fichier int foo; // espace de noms membre pour cette struct foo, portée fichier enum bar { // espace de noms d'étiquette, portée fichier RED // espace de noms ordinaire, portée fichier } bar; // espace de noms membre pour cette struct foo, portée fichier struct foo* p; // OK : utilise le nom "foo" d'étiquette/portée fichier }; enum bar x; // OK : utilise bar d'étiquette/portée fichier // int foo; // Erreur : espace de noms ordinaire foo déjà dans la portée //union foo { int a, b; }; // Erreur : espace de noms d'étiquette foo dans la portée int main(void) { goto foo; // OK utilise "foo" de l'espace de noms d'étiquette/portée fonction struct foo { // espace de noms d'étiquette, portée bloc (masque la portée fichier) enum bar x; // OK, utilise "bar" de l'espace de noms d'étiquette/portée fichier }; typedef struct foo foo; // OK : utilise foo de l'espace de noms d'étiquette/portée bloc // définit foo ordinaire de portée bloc (masque la portée fichier) (foo){.x=RED}; // utilise foo ordinaire/portée bloc et RED ordinaire/portée fichier foo:; // espace de noms d'étiquette, portée fonction }
Références
- Norme C17 (ISO/CEI 9899:2018) :
-
- 6.2.3 Espaces de noms des identificateurs (p: 29-30)
- Norme C11 (ISO/CEI 9899:2011) :
-
- 6.2.3 Espaces de noms des identificateurs (p: 37)
- Norme C99 (ISO/CEI 9899:1999) :
-
- 6.2.3 Espaces de noms des identificateurs (p: 31)
- Norme C89/C90 (ISO/IEC 9899:1990) :
-
- 3.1.2.3 Espaces de noms des identificateurs
Voir aussi
|
Documentation C++
pour
Name lookup
|