significado - Declaración o definición en C
que significan los lazos amarillos en cataluña (5)
De las variables externas Wiki :
Si ni la palabra clave externa ni un valor de inicialización están presentes, la declaración puede ser una declaración o una definición. Es responsabilidad del compilador analizar los módulos del programa y decidir.
No pude comprender completamente el significado de esta declaración con respecto a C. Por ejemplo, implica que:
int i;
¿No es necesariamente una declaración (como lo he estado asumiendo hasta ahora), pero también podría ser una definición (por definición de Definición y Declaración en la misma página web, sin juegos de palabras)?
En pocas palabras, es la declaración anterior: a. sólo una declaración, o b. declaración + definición?
Referencia: Declaración de variables y definición.
Resumen de las respuestas recibidas:
Declaration Definition Tentative Definition Initialized int i; (inside a block) Yes Yes No No int i=5; (inside a block) Yes Yes No Yes(to 5) int i; (otherwise) Yes No Yes Yes(to 0) extern int i; Yes No No No All definitions are declarations but not vice-versa.
Como C usa los términos:
Una "definición" crea algo (que ocupa algún tipo de memoria). También describe algo. Esto significa que una "definición" es también una "declaración".
Una "declaración" simplemente describe algo. La idea es que el compilador necesita saber cómo construir el código que usa lo que se define en otro lugar. Más tarde, el enlazador luego vincula el uso al algo.
Las declaraciones le permiten compilar el código y vincularlo (más adelante) como un paso separado.
De la especificación C99:
Una declaración de un identificador para un objeto que tiene un alcance de archivo sin un inicializador, y sin un especificador de clase de almacenamiento o con el estático del especificador de clase de almacenamiento, constituye una definición provisional. Si una unidad de traducción contiene una o más definiciones tentativas para un identificador, y la unidad de traducción no contiene una definición externa para ese identificador, entonces el comportamiento es exactamente como si la unidad de traducción contiene una declaración de alcance de archivo de ese identificador, con el tipo compuesto como del final de la unidad de traducción, con un inicializador igual a 0.
Este es un caso en el que una declaración simple sin un inicializador puede ser una declaración.
En el contexto de las variables:
Una declaración de una variable es una declaración que describe cómo se ve esta variable. Asi que:
extern int x;
en alcance global se traduce a: "en alguna parte del código, hay una variable llamada
x
que tiene tipoint
y enlace externo. Es necesaria una declaración antes de referirse ax
. (Lo mismo ocurre con las declaraciones de funciones).Una definición es una declaración que crea una instancia de esta variable. Asi que:
int x;
en ámbito global crea una única variable de tipo
int
con enlace externo. Entonces, si colocara esa línea en un encabezado, cada unidad de traducción, incluido ese encabezado, intentaría crear su propia copia dex
, lo cual no es deseable, por eso solo tenemos declaraciones en los archivos de encabezado. Lo mismo ocurre con las funciones: si proporciona el cuerpo de la función, es una definición.
Además, formalmente, cada definición es un tipo de declaración, ya que también tiene que especificar el aspecto de esta variable / función, por lo que si una definición ya existe en un ámbito determinado, no necesita declaraciones adicionales para usarla.
La norma C dice que
Una definición de un identificador es una declaración para ese identificador que: para un objeto, hace que el almacenamiento se reserve para ese objeto (...)
Las definiciones abarcan declaraciones, es decir, cada definición es necesariamente una declaración, por lo que no tiene sentido decir que
int i;
no es una declaracion Es una declaración que también pasa a ser una definición. O bien, es una definición, de ahí una declaración.
Suponiendo que está en el ámbito del archivo es una "definición provisional". A partir de 6.9.2 / 2 "Definiciones de objetos externos":
Una declaración de un identificador para un objeto que tiene un alcance de archivo sin un inicializador, y sin un especificador de clase de almacenamiento o con el estático del especificador de clase de almacenamiento, constituye una definición provisional. Si una unidad de traducción contiene una o más definiciones tentativas para un identificador, y la unidad de traducción no contiene una definición externa para ese identificador, entonces el comportamiento es exactamente como si la unidad de traducción contiene una declaración de alcance de archivo de ese identificador, con el tipo compuesto como del final de la unidad de traducción, con un inicializador igual a 0.
Esto significa que sería válido tener también lo siguiente en la unidad de traducción:
int i = 42;
dado que esa declaración tiene un inicializador explícito, es la definición de la variable i
.
En cuanto a si la declaración está en un ámbito de bloque, la norma dice lo siguiente (6.2.2 / 2 "Enlaces de identificadores"):
Cada declaración de un identificador sin vínculo denota una entidad única.
...
(párrafo 6) Los siguientes identificadores no tienen vinculación: ... un identificador de ámbito de bloque para un objeto declarado sin el especificador de clase de almacenamiento extern.
Así que en el ámbito de bloque, la declaración también sería una definición.