2012-06-15 23 views
20

Hice 2 proyectos, el primero en C y el segundo en C++, ambos funcionan con el mismo comportamiento.variables globales estáticas y externas en C y C++

C proyecto:

header.h

int varGlobal=7; 

main.c

#include <stdio.h> 
#include <stdlib.h> 
#include "header.h" 

void function(int i) 
{ 
    static int a=0; 
    a++; 
    int t=i; 
    i=varGlobal; 
    varGlobal=t; 
    printf("Call #%d:\ni=%d\nvarGlobal=%d\n\n",a,i,varGlobal,t); 
} 

int main() { 
    function(4); 
    function(6); 
    function(12); 
    return 0; 
} 

C++ proyecto:

header.h

int varGlobal=7; 

main.cpp

#include <iostream> 
#include "header.h" 
using namespace std; 

void function(int i) 
{ 
    static int a=0; 
    int t=i; 
    a++; 
    i=varGlobal; 
    varGlobal=t; 
    cout<<"Call #"<<a<<":"<<endl<<"i="<<i<<endl<<"varGlobal="<<varGlobal<<endl<<endl; 
} 

int main() { 
    function(4); 
    function(6); 
    function(12); 
    return 0; 
} 

leí que las variables globales son extern por defecto y en C y estática por defecto en C++; Entonces, ¿por qué funciona el código C++?

Me refiero a int varGlobal = 7; es igual que static int varGlobal = 7; y si es estático, puede usarse solo en el archivo que fue declarado, ¿no?

+0

primera nota contenido que 'include' simplemente copiar-pastas. Entonces, para ese ejemplo de archivo único, se debe eliminar para simplificar. –

Respuesta

63

Las variables globales no son extern ni static por defecto en C y C++. Cuando declara una variable como static, la está restringiendo al archivo fuente actual. Si lo declara como extern, está diciendo que la variable existe, pero está declarada en otro lugar, y si no la declara en otro lugar (sin la palabra clave extern) obtendrá un error de enlace (no se encuentra el símbolo).

Su código se interrumpirá cuando tenga más archivos fuente, incluido ese encabezado, en el tiempo del enlace tendrá múltiples referencias a varGlobal. Si lo declara como static, funcionará con varias fuentes (es decir, compilará y vinculará), pero cada fuente tendrá su propia varGlobal.

Lo que puede hacer en C++, que no se puede en C, es declarar la variable como const en la cabecera, así:

const int varGlobal = 7; 

e incluir en múltiples fuentes, sin romper cosas a la tiempo de enlace La idea es reemplazar el antiguo estilo C #define por constantes.

Si necesita una variable global visible en múltiples fuentes y no const, declarará como extern en la cabecera, y declarar de nuevo, esta vez sin la keywork externo, en un archivo de origen:

cabecera incluida por varios archivos:

extern int varGlobal; 

En uno de los archivos de origen:

int varGlobal = 7; 
+3

Como acabo de descubrir, * hay * una diferencia entre C y C++, pero solo se aplica a los objetos ** const **: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp? topic =% 2Fcom.ibm.xlcpp8l.doc% 2Flanguage% 2Fref% 2Fconst_cv_qualifier.htm –

+0

Si va a poner cosas en los encabezados, algunos compiladores/vinculadores se quejarán de los símbolos definidos de forma múltiple. Ejemplo: 'const int varGlobal = 7;' Como lo está declarando 'const' puede tratarse como una constante global, pero algunos compiladores no son tan inteligentes. Lo que sí funciona, siempre, es declarar cosas 'const' estáticas en el archivo de encabezado, así:' static const int varGlobal = 7; 'De esa manera, incluso si el compilador es estúpido, no agregará el símbolo al externo la tabla de símbolos y el enlazador nunca verá símbolos definidos de forma múltiple. – steveha

+0

@steveha Declarar una constante como "constante estática" causará advertencias molestas en los archivos que incluyen el encabezado, pero no use la constante (por supuesto, dependiendo de su compilador y advertencias habilitadas). – fbafelipe

6

Cuando #include un encabezado, es exactamente como si pusiera el código en el archivo de origen. En ambos casos, la variable varGlobal se define en la fuente, por lo que funcionará independientemente de cómo se declare.

También como se señala en los comentarios, las variables de C++ en el alcance del archivo no son de alcance estático, aunque se asignarán al almacenamiento estático. Si la variable fuera un miembro de la clase, por ejemplo, tendría que ser accesible para otras unidades de compilación en el programa por defecto y los miembros no pertenecientes a la clase no son diferentes.

+3

Además, el OP es incorrecto en la suposición de que la variable declarada globalmente es estática por defecto en C++. Tienen external * linkage *, al igual que en C. Las variables globales tienen static * duration * en C y C++, por lo que puede ser confuso. – nos

+0

Entonces la regla se aplica a los archivos * .c an * .cpp pero no a los archivos * .h? ¡Gracias! – Cristi

+0

Estaba equivocado ... ¡Gracias! – Cristi