Lookup and name spaces
Wenn ein Identifier in einem C-Programm angetroffen wird, wird eine Suche durchgeführt, um die Deklaration zu lokalisieren, die diesen Identifier eingeführt hat und die gegenwärtig im Gültigkeitsbereich ist. C erlaubt, dass mehr als eine Deklaration für denselben Identifier gleichzeitig im Gültigkeitsbereich sein kann, wenn diese Identifier zu verschiedenen Kategorien gehören, genannt Namensräume :
|
4)
Globaler Attribut-Namensraum:
Attribut-Tokens
definiert durch den Standard oder implementierungsdefinierte Attribut-Präfixe.
5)
Nicht-standardisierte Attributnamen: Attributnamen, die Attribut-Präfixen folgen. Jedes Attribut-Präfix hat einen separaten Namensraum für die implementierungsdefinierten Attribute, die es einführt.
|
(seit C23) |
Zum Zeitpunkt der Namenssuche wird der Namensraum eines Identifikators durch die Art seiner Verwendung bestimmt:
|
4)
Ein Bezeichner, der direkt in einer Attributspezifikation erscheint (
[
[
...
]
]
) wird im globalen Attributnamensraum gesucht.
5)
Ein Bezeichner, der auf den
::
Token folgt, der einem Attributpräfix folgt, wird im Namensraum gesucht, der durch das Attributpräfix eingeführt wird.
|
(seit C23) |
Inhaltsverzeichnis |
Hinweise
Die Namen von Makros gehören zu keinem Namensraum, da sie vom Präprozessor vor der semantischen Analyse ersetzt werden.
Es ist gängige Praxis, die Namen von Structs/Unions/Enums mittels einer typedef -Deklaration in den Namensraum der gewöhnlichen Bezeichner einzufügen:
struct A { }; // führt den Namen A im Tag-Namensraum ein typedef struct A A; // zuerst wird A nach "struct" gesucht und findet einen im Tag-Namensraum // führt dann den Namen A im gewöhnlichen Namensraum ein struct A* p; // OK, dieses A wird im Tag-Namensraum gesucht A* q; // OK, dieses A wird im gewöhnlichen Namensraum gesucht
Ein bekanntes Beispiel für die Verwendung desselben Bezeichners in zwei Namensräumen ist der Bezeichner
stat
aus dem POSIX-Header
sys/stat.h
. Er
benennt eine Funktion
, wenn er als gewöhnlicher Bezeichner verwendet wird, und
kennzeichnet eine Struktur
, wenn er als Tag verwendet wird.
Im Gegensatz zu C++ sind Aufzählungskonstanten keine struct-Mitglieder, und ihr Namensraum ist der Namensraum gewöhnlicher Bezeichner, und da es in C keinen struct-Gültigkeitsbereich gibt, ist ihr Gültigkeitsbereich der Gültigkeitsbereich, in dem die struct-Deklaration erscheint:
struct tagged_union { enum {INT, FLOAT, STRING} type; union { int integer; float floating_point; char *string; }; } tu; tu.type = INT; // OK in C, Fehler in C++
|
Wenn ein Standardattribut, ein Attributpräfix oder ein nicht-standardisiertes Attribut nicht unterstützt wird, wird das ungültige Attribut selbst ignoriert, ohne einen Fehler zu verursachen. |
(since C23) |
Beispiel
void foo (void) { return; } // gewöhnlicher Namensraum, Dateigültigkeitsbereich struct foo { // Tag-Namensraum, Dateigültigkeitsbereich int foo; // Mitgliedsnamensraum für diese struct foo, Dateigültigkeitsbereich enum bar { // Tag-Namensraum, Dateigültigkeitsbereich RED // gewöhnlicher Namensraum, Dateigültigkeitsbereich } bar; // Mitgliedsnamensraum für diese struct foo, Dateigültigkeitsbereich struct foo* p; // OK: verwendet Tag/Dateigültigkeitsbereich-Name "foo" }; enum bar x; // OK: verwendet Tag/Dateigültigkeitsbereich bar // int foo; // Fehler: gewöhnlicher Namensraum foo bereits im Gültigkeitsbereich //union foo { int a, b; }; // Fehler: Tag-Namensraum foo im Gültigkeitsbereich int main(void) { goto foo; // OK verwendet "foo" aus Label-Namensraum/Funktionsgültigkeitsbereich struct foo { // Tag-Namensraum, Blockgültigkeitsbereich (verdeckt Dateigültigkeitsbereich) enum bar x; // OK, verwendet "bar" aus Tag-Namensraum/Dateigültigkeitsbereich }; typedef struct foo foo; // OK: verwendet foo aus Tag-Namensraum/Blockgültigkeitsbereich // definiert gewöhnlichen Blockgültigkeitsbereich-foo (verdeckt Dateigültigkeitsbereich) (foo){.x=RED}; // verwendet gewöhnlichen/Blockgültigkeitsbereich-foo und gewöhnlichen/Dateigültigkeitsbereich-RED foo:; // Label-Namensraum, Funktionsgültigkeitsbereich }
Referenzen
- C17-Standard (ISO/IEC 9899:2018):
-
- 6.2.3 Namensräume von Bezeichnern (S: 29-30)
- C11-Standard (ISO/IEC 9899:2011):
-
- 6.2.3 Namensräume von Bezeichnern (S: 37)
- C99-Standard (ISO/IEC 9899:1999):
-
- 6.2.3 Namensräume von Bezeichnern (S: 31)
- C89/C90 Standard (ISO/IEC 9899:1990):
-
- 3.1.2.3 Namensräume von Bezeichnern
Siehe auch
|
C++-Dokumentation
für
Name lookup
|