Пространства имён поиска и имён
Когда в программе на языке C встречается идентификатор, выполняется поиск, чтобы найти объявление этого идентификатора, которое в данный момент в области видимости. Язык C допускает одновременное нахождение в области видимости более одного объявления одного и того же идентификатора, если эти идентификаторы принадлежат к разным категориям, называемым пространствами имён:
| 4) Пространство имён глобальных атрибутов: токены атрибутов, определённые стандартом или атрибутами префиксов, определёнными реализацией. 5) Пространство имён нестандартных имён атрибутов: имена атрибутов, следующие за префиксами атрибутов. Каждый префикс атрибута имеет отдельное пространство имён для вводимых им имён реализационных атрибутов. | (с C23) |
В момент поиска пространство имён идентификатора определяется способом его использования:
struct, union, или enum, ищется в пространстве имён тегов.
4) Идентификатор, непосредственно появляющийся в спецификаторе атрибута ([[...]]), ищется в глобальном пространстве имён атрибутов. 5) Идентификатор, следующий за токеном :: после префикса атрибута, ищется в пространстве имён, введённом префиксом атрибута.
|
(с C23) |
Примечания
Имена макросов не входят ни в одно пространство имён, потому что они заменяются препроцессором до семантического анализа.
Распространённой практикой является введение имён структур/объединений/перечислений в пространство имён обычных идентификаторов с помощью объявления typedef:
struct A { }; // introduces the name A in tag name space
typedef struct A A; // first, lookup for A after "struct" finds one in tag name space
// then introduces the name A in the ordinary name space
struct A* p; // OK, this A is looked up in the tag name space
A* q; // OK, this A is looked up in the ordinary name spaceИзвестным примером одного и того же идентификатора, используемого в двух пространствах имён, является идентификатор 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; // OK in C, error in C++|
Если стандартный атрибут, префикс атрибута или имя нестандартного атрибута не поддерживаются, сам неверный атрибут игнорируется без вывода ошибки. |
(с C23) |
Пример
void foo (void) { return; } // ordinary name space, file scope
struct foo { // tag name space, file scope
int foo; // member name space for this struct foo, file scope
enum bar { // tag name space, file scope
RED // ordinary name space, file scope
} bar; // member name space for this struct foo, file scope
struct foo* p; // OK: uses tag/file scope name "foo"
};
enum bar x; // OK: uses tag/file-scope bar
// int foo; // Error: ordinary name space foo already in scope
//union foo { int a, b; }; // Error: tag name space foo in scope
int main(void)
{
goto foo; // OK uses "foo" from label name space/function scope
struct foo { // tag name space, block scope (hides file scope)
enum bar x; // OK, uses "bar" from tag name space/file scope
};
typedef struct foo foo; // OK: uses foo from tag name space/block scope
// defines block-scope ordinary foo (hides file scope)
(foo){.x=RED}; // uses ordinary/block-scope foo and ordinary/file-scope RED
foo:; // label name space, function scope
}Ссылки
- Стандарт 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++ для Поиск имён |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/name_space