2011-01-22 14 views
20

De External Variables Wiki:Declaración o definición en C

Si ni la palabra clave extern ni un valor de inicialización están presentes, la declaración puede ser o bien una declaración o una definición. Depende del compilador analizar los módulos del programa y decidir.

I no fue capaz de agarrar completamente el significado de esta afirmación con respecto a C. Por ejemplo, implica que:

int i; 

no es necesariamente una declaración (como he estado asumiendo hasta ahora), pero también podría ser una definición (por definición de Definición & Declaración en la misma página web, sin juegos de palabras destinados)

En pocas palabras, es la declaración anterior: a. solo una declaración, o b. declaración + definición?

Referencia: Variable declaration and definition

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. 

Respuesta

13

El estándar de C dice que

Una definición de un identificador es una declaración para dicho identificador que: para un objeto, hace que el almacenamiento a reservar 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 declaración. Es es una declaración que también es una definición. O bien, es una definición, de ahí una declaración.

+7

Sin embargo, es una buena idea tener en cuenta que no todas las declaraciones son definiciones. –

15

asumiendo que es en el ámbito de archivo que es una 'definición tentativa'. De 6.9.2/2 "definiciones de objetos externos":

Una declaración de un identificador para un objeto que tiene presentar alcance sin un inicializador, y sin un especificador de clase de almacenamiento o con el especificador de clase de almacenamiento estático , constituye una definición tentativa . Si una unidad de traducción contiene una o más definiciones tentativas para un identificador , y la unidad de traducción no contiene ninguna 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 identificador tipo compuesto a partir de finales de la unidad de traducción, con un inicializador igual a 0.

Esto significa que sería válido también para tener lo siguiente en la unidad de traducción:

int i = 42; 

desde esa declaración La ración tiene un inicializador explícito, es la definición de la variable i.

Por lo que si la declaración está en un ámbito de bloque, el estándar dice que los siguientes (6.2.2/2 "Vínculos de identificadores"):

Cada declaración de un identificador con no denota vinculación una entidad única.

...

(párrafo 6) Los siguientes identificadores tienen ninguna vinculación: ...un identificador de alcance bloque para un objeto declaró sin la extern especificador de clase de almacenamiento .

Por lo tanto, en el alcance del bloque, la declaración sería también una definición.

+0

Suponiendo que está dentro de un bloque (sin alcance de archivo) ...? –

+0

@crypto: actualizó la respuesta para cubrir una declaración de alcance de bloque. –

+0

Gracias por la respuesta detallada. Seleccioné la respuesta de Bavarious porque es más directa. –

4

En el contexto de variables:

  • Una declaración de una variable es una declaración que describe cómo esta variable se parece. Por lo tanto:

    extern int x; 
    

    en el ámbito global se traduce en: "en algún lugar del código, hay una variable llamada x la que tiene el tipo int y vinculación extern Una declaración es necesaria antes de que usted se refieren a x (Lo mismo se aplica a.. declaraciones de funciones.)

  • una definición es una declaración que crea una instancia de esta variable tanto:.

    int x; 
    

    en el ámbito global crea un único variab le del tipo int con enlace externo. Entonces, si pusiera esa línea en un encabezado, cada unidad de traducción, incluido ese encabezado, intentaría crear su propia copia de x, lo cual es indeseable, 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 una especie de declaración, ya que también tiene que especificar cómo esta variable/función se parece - por lo que si una definición ya existe en un ámbito determinado, que no es necesario ningún declaraciones adicionales para usarlo.

1

De la especificación C99:

Una declaración de un identificador para un objeto que tiene presentar alcance sin un inicializador y sin un especificador de clase de almacenamiento o con el especificador de clase de almacenamiento estático, constituye una definición tentativa.Si una unidad de traducción contiene una o más definiciones tentativas para un identificador , y la unidad de traducción no contiene ninguna 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 identificador tipo compuesto a partir de finales de la unidad de traducción, con un inicializador igual a 0.

Así que este es un caso en que una declaración simple sin un inicializador puede ser una declaración.

+0

¿Es posible que agregue su respuesta a la de Michael, ya que se refiere a la misma parte del Estándar C99? –

+0

Esa cita de la especificación está hablando del comportamiento del compilador. Está diciendo que este caso particular de declaración podría terminar siendo una definición. – davep

+0

Parece que agregó la cita a su respuesta ... –

1

Como C utiliza los términos:

una "definición" crea algo (que ocupa una especie de memoria). También describe algo. Esto significa que una "definición" también es 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 definido en otro lugar. Más tarde, el enlazador vincula el uso al algo.

Las declaraciones le permiten compilar el código y vincularlo (más tarde) como un paso separado.

Cuestiones relacionadas