Noté que si declaro una variable global varias veces, el compilador ni siquiera genera una advertencia.
Sin embargo, si declaro una variable local en una función varias veces, por ejemplo, el compilador gcc genera un error y no compila el archivo. (Pregunto en términos de gcc, pero esta es más una pregunta de diseño de lenguaje general, no una pregunta sobre gcc, porque creo que es probable que otros compiladores se comporten de manera similar).
¿Cuál es la explicación de este comportamiento?
extern int x;
, que es una declaración, la compilación se cancelará ya que no hay lugar donde se asigne memoria a la variable.Respuestas:
De acuerdo con las pautas de codificación :
La variable local no tiene vinculación. entonces hay un nombre Se produce colisión. Entonces, la declaración múltiple de la variable local no es posible.
La variable global tiene enlace externo. Entonces, es posible la declaración múltiple de variables globales.
fuente
@msc ofrece una buena introducción a las reglas detrás de este comportamiento.
C tiene tres tipos de declaraciones globales para objetos, a saber, las que están (y estoy pasando por alto
static
aquí):extern int a;
int a = 3;
oextern int a = 3;
int a;
Se permiten múltiples declaraciones de tipo 1 y 3, mientras que a lo sumo se permite una definición (tipo 2).
Si también está preguntando sobre la motivación de estas reglas, es un soporte para la compilación por separado . (Ver unidad de traducción ).
Para dividir un programa en múltiples archivos compilados por separado, necesitamos algunas características, a saber (a) poder declarar sin definir necesariamente , y (b) declaración de reenvío .
Dentro de una unidad de traducción necesitamos poder hacer referencia a funciones y datos globales en otra unidad de traducción. Y también nos gustaría realizar algunas comprobaciones de errores, aquí, para descubrir definiciones faltantes y definiciones duplicadas erróneas.
A veces, en la misma unidad de traducción, declaramos un global y luego lo definimos más adelante. Esto puede suceder si necesitamos una declaración directa por alguna razón, o si usamos un archivo de encabezado común (que proporciona declaraciones) dentro de la unidad de traducción que también ofrece definiciones explícitas.
Dado que la compilación separada en C se aplica mediante la vinculación de funciones globales y datos, estas características son necesarias a nivel global pero no a nivel local.
Como señala @msc, nada de esto es necesario para las variables locales, ya que no tienen vinculación.
C (como muchos otros lenguajes) no proporciona enlaces para variables locales, ya que el lenguaje no intenta admitir una sola función que abarque múltiples unidades de traducción separadas.
(Por supuesto, puede hacer que una función abarque varios archivos de origen, pero no múltiples unidades de traducción).
Una definición provisional funciona igual que una declaración, ya que está permitida en múltiples unidades de traducción (y también se combina muy bien con otras declaraciones). Sin embargo, si no hay una definición (no provisional) para el identificador en todo el programa, el conjunto de (una o más) definiciones provisionales en varias unidades de traducción (para un identificador) se toma como una definición para el objeto cuyo inicializador es cero.
Esto se puede implementar al colocarlos en la sección .BSS con el tamaño y la alineación adecuados; el enlazador los emparejará con la definición verdadera si se encuentra, o bien los emparejará entre sí, dándoles espacio cero en BSS.
La noción de compilación separada se puede soportar por completo sin la característica de las definiciones provisionales; creo que las definiciones provisionales existen principalmente por razones históricas. (No digo que no sean útiles, solo si el lenguaje se creó hoy, esto podría verse como innecesario y, por lo tanto, no se ofrecerá).
fuente