Lookup and name spaces
Когда в программе на C встречается идентификатор , выполняется поиск для нахождения объявления , которое ввело этот идентификатор и которое в данный момент находится в области видимости . C позволяет нескольким объявлениям одного идентификатора одновременно находиться в области видимости, если эти идентификаторы принадлежат к разным категориям, называемым пространствами имён :
|
4)
Пространство имен глобальных атрибутов:
токены атрибутов
определенные стандартом или префиксы атрибутов, определенные реализацией.
5)
Нестандартные имена атрибутов: имена атрибутов, следующие за префиксами атрибутов. Каждый префикс атрибута имеет отдельное пространство имен для определяемых реализацией атрибутов, которые он вводит.
|
(since C23) |
В момент поиска пространство имён идентификатора определяется способом его использования:
|
4)
идентификатор, который непосредственно появляется в спецификаторе атрибута (
[
[
...
]
]
), ищется в глобальном пространстве имен атрибутов.
5)
идентификатор, следующий за токеном
::
после префикса атрибута, ищется в пространстве имен, введенном префиксом атрибута.
|
(since C23) |
Содержание |
Примечания
Имена макросов не принадлежат какому-либо пространству имён, поскольку они заменяются препроцессором до семантического анализа.
Обычной практикой является внедрение имён структур/объединений/перечислений в пространство имён обычных идентификаторов с помощью typedef объявления:
struct A { }; // вводит имя A в пространстве имен тегов typedef struct A A; // сначала поиск A после "struct" находит его в пространстве имен тегов // затем вводит имя A в обычном пространстве имен struct A* p; // OK, этот A ищется в пространстве имен тегов A* q; // OK, этот A ищется в обычном пространстве имен
Хорошо известным примером использования одного и того же идентификатора в двух пространствах имён является идентификатор
stat
из заголовка POSIX
sys/stat.h
. Он
обозначает функцию
при использовании в качестве обычного идентификатора и
указывает на структуру
при использовании в качестве тега.
В отличие от C++, константы перечисления не являются членами структуры, их пространство имён — это пространство имён обычных идентификаторов, и поскольку в C нет области видимости структуры, их область видимости — это область видимости, в которой появляется объявление структуры:
struct tagged_union { enum {INT, FLOAT, STRING} type; union { int integer; float floating_point; char *string; }; } tu; tu.type = INT; // Корректно в C, ошибка в C++
|
Если стандартный атрибут, префикс атрибута или нестандартное имя атрибута не поддерживается, сам некорректный атрибут игнорируется без вызова ошибки. |
(since C23) |
Пример
void foo (void) { return; } // обычное пространство имен, область видимости файла struct foo { // пространство имен тегов, область видимости файла int foo; // пространство имен членов для этой struct foo, область видимости файла enum bar { // пространство имен тегов, область видимости файла RED // обычное пространство имен, область видимости файла } bar; // пространство имен членов для этой struct foo, область видимости файла struct foo* p; // OK: использует имя "foo" из пространства тегов/области файла }; enum bar x; // OK: использует bar из пространства тегов/области файла // int foo; // Ошибка: обычное пространство имен foo уже в области видимости //union foo { int a, b; }; // Ошибка: пространство имен тегов foo в области видимости int main(void) { goto foo; // OK использует "foo" из пространства имен меток/области функции struct foo { // пространство имен тегов, область блока (скрывает область файла) enum bar x; // OK, использует "bar" из пространства имен тегов/области файла }; typedef struct foo foo; // OK: использует foo из пространства имен тегов/области блока // определяет обычное foo в области блока (скрывает область файла) (foo){.x=RED}; // использует обычное/блочное foo и обычное/файловое RED foo:; // пространство имен меток, область функции }
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.2.3 Пространства имён идентификаторов (стр: 29-30)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.2.3 Пространства имён идентификаторов (стр: 37)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 6.2.3 Пространства имён идентификаторов (стр: 31)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 3.1.2.3 Пространства имён идентификаторов
Смотрите также
|
Документация C++
для
Поиска имён
|