Lookup and name spaces
Cuando se encuentra un identificador en un programa C, se realiza una búsqueda para localizar la declaración que introdujo ese identificador y que está actualmente en ámbito . C permite que más de una declaración para el mismo identificador esté en ámbito simultáneamente si estos identificadores pertenecen a diferentes categorías, llamadas espacios de nombres :
|
4)
Espacio de nombres de atributos globales:
tokens de atributo
definidos por el estándar o prefijos de atributo definidos por la implementación.
5)
Nombres de atributos no estándar: nombres de atributos que siguen a prefijos de atributo. Cada prefijo de atributo tiene un espacio de nombres separado para los atributos definidos por la implementación que introduce.
|
(desde C23) |
En el momento de la búsqueda, el espacio de nombres de un identificador se determina por la forma en que se utiliza:
|
4)
identificador que aparece directamente en un especificador de atributo (
[
[
...
]
]
) se busca en el espacio de nombres global de atributos.
5)
identificador que sigue al token
::
después de un prefijo de atributo se busca en el espacio de nombres introducido por el prefijo de atributo.
|
(desde C23) |
Contenidos |
Notas
Los nombres de las macros no forman parte de ningún espacio de nombres porque son reemplazados por el preprocesador antes del análisis semántico.
Es una práctica común inyectar los nombres de struct/union/enum en el espacio de nombres de los identificadores ordinarios usando una typedef declaration:
struct A { }; // introduce el nombre A en el espacio de nombres de etiquetas typedef struct A A; // primero, la búsqueda de A después de "struct" encuentra uno en el espacio de nombres de etiquetas // luego introduce el nombre A en el espacio de nombres ordinario struct A* p; // OK, este A se busca en el espacio de nombres de etiquetas A* q; // OK, este A se busca en el espacio de nombres ordinario
Un ejemplo conocido del mismo identificador utilizado en dos espacios de nombres es el identificador
stat
del encabezado POSIX
sys/stat.h
. Este
nombra una función
cuando se utiliza como identificador ordinario y
indica una struct
cuando se utiliza como etiqueta.
A diferencia de C++, las constantes de enumeración no son miembros de struct, y su espacio de nombres es el espacio de nombres de identificadores ordinarios, y dado que no hay ámbito de struct en C, su ámbito es el ámbito en el que aparece la declaración del struct:
struct tagged_union { enum {INT, FLOAT, STRING} type; union { int integer; float floating_point; char *string; }; } tu; tu.type = INT; // Correcto en C, error en C++
|
Si un atributo estándar, un prefijo de atributo o un nombre de atributo no estándar no es compatible, el atributo inválido en sí se ignora sin causar un error. |
(since C23) |
Ejemplo
void foo (void) { return; } // espacio de nombres ordinario, ámbito de archivo struct foo { // espacio de nombres de etiquetas, ámbito de archivo int foo; // espacio de nombres de miembros para este struct foo, ámbito de archivo enum bar { // espacio de nombres de etiquetas, ámbito de archivo RED // espacio de nombres ordinario, ámbito de archivo } bar; // espacio de nombres de miembros para este struct foo, ámbito de archivo struct foo* p; // OK: usa el nombre "foo" de ámbito de etiqueta/archivo }; enum bar x; // OK: usa bar de ámbito de etiqueta/archivo // int foo; // Error: el espacio de nombres ordinario foo ya está en ámbito //union foo { int a, b; }; // Error: el espacio de nombres de etiquetas foo está en ámbito int main(void) { goto foo; // OK usa "foo" del espacio de nombres de etiquetas/ámbito de función struct foo { // espacio de nombres de etiquetas, ámbito de bloque (oculta el ámbito de archivo) enum bar x; // OK, usa "bar" del espacio de nombres de etiquetas/ámbito de archivo }; typedef struct foo foo; // OK: usa foo del espacio de nombres de etiquetas/ámbito de bloque // define foo ordinario de ámbito de bloque (oculta el ámbito de archivo) (foo){.x=RED}; // usa foo ordinario/ámbito-de-bloque y RED ordinario/ámbito-de-archivo foo:; // espacio de nombres de etiquetas, ámbito de función }
Referencias
- Estándar C17 (ISO/IEC 9899:2018):
-
- 6.2.3 Espacios de nombres de identificadores (p: 29-30)
- Estándar C11 (ISO/IEC 9899:2011):
-
- 6.2.3 Espacios de nombres de identificadores (p: 37)
- Estándar C99 (ISO/IEC 9899:1999):
-
- 6.2.3 Espacios de nombres de identificadores (p: 31)
- Estándar C89/C90 (ISO/IEC 9899:1990):
-
- 3.1.2.3 Espacios de nombres de identificadores
Véase también
|
Documentación de C++
para
Name lookup
|