External and tentative definitions
En el nivel superior de una unidad de traducción (es decir, un archivo fuente con todos los #includes después del preprocesador), cada programa C es una secuencia de declaraciones , que declaran funciones y objetos con enlace externo o interno . Estas declaraciones se conocen como declaraciones externas porque aparecen fuera de cualquier función.
extern int n; // declaración externa con enlace externo int b = 1; // definición externa con enlace externo static const char *c = "abc"; // definición externa con enlace interno int f(void) // definición externa con enlace externo { int a = 1; // no externa return b; } static void x(void) // definición externa con enlace interno { }
Los objetos declarados con una declaración externa tienen duración de almacenamiento estática , y como tales no pueden usar los especificadores auto o register excepto que auto puede usarse para inferencia de tipos (desde C23) . Los identificadores introducidos por declaraciones externas tienen ámbito de archivo .
Contenidos |
Definiciones tentativas
Una definición tentativa es una declaración externa sin un inicializador, y sin un especificador de clase de almacenamiento o con el especificador static .
Una definición tentativa es una declaración que puede o no actuar como una definición. Si se encuentra una definición externa real anterior o posteriormente en la misma unidad de traducción, entonces la definición tentativa simplemente actúa como una declaración.
int i1 = 1; // definición, enlace externo int i1; // definición tentativa, actúa como declaración porque i1 está definido extern int i1; // declaración, se refiere a la definición anterior extern int i2 = 3; // definición, enlace externo int i2; // definición tentativa, actúa como declaración porque i2 está definido extern int i2; // declaración, se refiere a la definición de enlace externo
Si no hay definiciones en la misma unidad de traducción, entonces la definición tentativa actúa como una definición real que empty-initializes el objeto.
int i3; // definición tentativa, enlace externo int i3; // definición tentativa, enlace externo extern int i3; // declaración, enlace externo // en esta unidad de traducción, i3 se define como si fuera "int i3 = 0;"
A diferencia de las declaraciones extern , que no cambian la vinculación de un identificador si una declaración previa la estableció, las definiciones tentativas pueden discrepar en vinculación con otra declaración del mismo identificador. Si dos declaraciones para el mismo identificador están en alcance y tienen diferente vinculación, el comportamiento es indefinido:
static int i4 = 2; // definición, enlace interno int i4; // Comportamiento indefinido: desacuerdo de enlace con la línea anterior extern int i4; // declaración, se refiere a la definición de enlace interno static int i5; // definición tentativa, enlace interno int i5; // Comportamiento indefinido: desacuerdo de enlace con la línea anterior extern int i5; // se refiere al anterior, cuyo enlace es interno
Una definición tentativa con enlace interno debe tener tipo completo.
static int i[]; // Error, tipo incompleto en una definición tentativa estática int i[]; // OK, equivalente a int i[1] = {0}; a menos que se redeclare más adelante en este archivo
Regla de una definición
Cada unidad de traducción puede tener cero o una definición externa de cada identificador con enlace interno (un global static ).
Si un identificador con enlace interno se utiliza en cualquier expresión que no sea
no-VLA,
(desde C99)
sizeof
,
_Alignof
(desde C11)
(hasta C23)
,
alignof
(desde C23)
, o
typeof
(desde C23)
, debe haber una y solo una definición externa para ese identificador en la unidad de traducción.
El programa completo puede tener cero o una definición externa de cada identificador con enlace externo .
Si un identificador con enlace externo se utiliza en cualquier expresión que no sea
no-VLA,
(desde C99)
sizeof
,
_Alignof
(desde C11)
(hasta C23)
,
alignof
(desde C23)
, o
typeof
(desde C23)
, debe existir una y solo una definición externa para ese identificador en algún lugar del programa completo.
Notas
|
Las definiciones inline en diferentes unidades de traducción no están restringidas por la regla de una definición. Consulte
|
(desde C99) |
Consulte duración de almacenamiento y enlace para el significado de la palabra clave extern con declaraciones en el ámbito de archivo
Consulte definiciones para la distinción entre declaraciones y definiciones.
Las definiciones tentativas se inventaron para estandarizar varios enfoques pre-C89 de declarar anticipadamente identificadores con enlace interno.
Referencias
- Estándar C23 (ISO/IEC 9899:2024):
-
- 6.9 Definiciones externas (p: TBD)
- Estándar C17 (ISO/IEC 9899:2018):
-
- 6.9 Definiciones externas (p: 113-116)
- Estándar C11 (ISO/IEC 9899:2011):
-
- 6.9 Definiciones externas (p: 155-159)
- Estándar C99 (ISO/IEC 9899:1999):
-
- 6.9 Definiciones externas (p: 140-144)
- Estándar C89/C90 (ISO/IEC 9899:1990):
-
- 3.7 DEFINICIONES EXTERNAS