2013-07-01 9 views
9

stavo eseguendo i seguenti codici compilati insieme come: gcc A.c B.c -o combinedEsterno in più file e l'eventuale doppia definizione

Programma A:

#include<stdio.h> 
int a=1; 
int b; 
int main() 
{ 
extern int a,b; 
fun(); 
printf("%d %d\n",a,b); 
} 

Programma B:

int a; 
int b=2; 
int fun() 
{ 
printf("%d %d\n",a,b); 
return 0; 
} 

a correre la " combinato "programma l'output era:

1 2 
1 2 
.210

Ora, ho un paio di dubbi su questo:

  1. Perché non è l'uscita:

  2. non un Are e b definito due volte?

Si prega di spiegare questi chiaramente, ho avuto un sacco di problemi di comprensione extern e pochi di questi dubbi continuano a venire di tanto in tanto.

Grazie in anticipo.

+1

si tenta di ingannare il compilatore e il compilatore ti ha ingannato. –

+5

Non si tratta di ingannare il compilatore, si tratta di ottenere i concetti corretti. – tapananand

risposta

3

Quindi, sto rispondendo alla mia domanda dopo molto tempo. Anche se la dichiarazione:

int b; è un decalaration e int b = 2; è la definizione

è corretto, ma il motivo per ognuno sta dando non è chiaro.

Se non ci fosse stato un int b = 2;, int b; era una definizione, quindi qual è la differenza?

La differenza sta nel modo in cui il linker gestisce più definizioni di simboli. Esiste un concetto di simboli deboli e forti.

L'assemblatore codifica questa informazione implicitamente nella tabella dei simboli del file oggetto rilocabile. Le funzioni e le variabili globali inizializzate ottengono forti simboli. Le variabili globali non inizializzate ottengono simboli deboli.

Quindi, in Program A, int a = 1 è un simbolo forte, mentre int b; è un simbolo debole, allo stesso modo in Program B, int b = 2 è un simbolo forte e mentre int a è debole.

Dato questo concetto di simboli forti e deboli, linker Unix utilizzano le seguenti regole per trattare con i simboli moltiplicano definite:

  1. Più simboli forti non sono ammessi.
  2. Dato un simbolo forte e più simboli deboli, scegliere il simbolo forte.
  3. Dato più simboli deboli, selezionare uno dei simboli deboli.

Quindi, ora possiamo discutere su ciò che sta accadendo nel caso di cui sopra.

  1. Tra int b = 2 e int b, il primo è un simbolo forte mentre il secondo è debole e quindi b è definito con il valore 2.
  2. Tra int a = 1 e int a, a è definito come 1 (stesso ragionamento).

Quindi, l'uscita 1 2.

1

Per quanto ne so: L'output sarà 1 2 e 1 2 perché si definiscono a e b come variabili esterne nella funzione principale. Quindi proverà a prendere il valore anche da altri file. Per quanto riguarda la seconda domanda, ritengo che il compilatore stia prendendo i valori inizializzati della variabile e li unisca perché sia ​​a che b sono definiti come variabile globale in entrambi i file. Il caso può essere diverso se entrambi sono stati definiti all'interno della funzione. Qualsiasi suggerimento o altri input sono i benvenuti.

3

Perché le variabili non sono definite due volte qui; sono dichiarati due volte però. Le funzioni prendono i valori dalla definizione delle variabili non dalla dichiarazione delle variabili.

Una dichiarazione introduce un identificatore e ne descrive il tipo. Tramite la dichiarazione assicuriamo al compilatore che questa variabile o funzione è stata definita da qualche altra parte nel programma e verrà fornita al momento del collegamento. Come per esempio la dichiarazione è:

extern int a;

Una definizione crea un'istanza in realtà/implementa questo identificatore. La definizione è: int a=5; O int a;

appena letto on this link per ulteriore riferimento.

there is this wonderful post su stackoverflow.

extern dice al compilatore che variabile è definita al di fuori in modo che appaia all'esterno della funzione e non ci trova:

int a=1 nel programma A e int b=2 in programma B

Per le variabili AUTO:

int a;//both definition and declaration

Per ulteriori informazioni sulle CLASSI DI STOCCAGGIO è possibile follow this link

int a al di fuori della funzione principale o di qualsiasi altra funzione è la dichiarazione (cioè GLOBAL) solo all'interno di qualsiasi funzione la sua definizione chiamata.

+0

Per quanto ne so int a; è sia dichiarazione che definizione e infatti al di fuori di qualsiasi funzione diventa anche inizializzazione con valore 0. int main() int. ( int a; // sia dichiarazione che definizione ... int a = 5; // dà errore definizione multipla di a. } Si può provare lo stesso anche per le variabili esterne. – tapananand

+0

Ya, conosco la differenza, ma quello che sto dicendo è scrivere int a; entrambi dichiara e definisce i.e. alloca memoria per a. Al di fuori di qualsiasi funzione, lo inizializza anche con un valore ben definito (0) e non con un valore spazzatura. – tapananand

+0

Ci scusiamo per il ritardo del problema di alimentazione .... Quello che dici potrebbe essere vero per le variabili Auto ma non per le variabili esterne, basta dare un'occhiata al link nella mia risposta. – 0decimal0

5

Una variabile può essere dichiarata molte volte, a condizione che le dichiarazioni siano coerenti tra loro e con la definizione. Può essere dichiarato in molti moduli, incluso il modulo in cui è stato definito, e anche molte volte nello stesso modulo.

Una variabile esterna può anche essere dichiarata all'interno di una funzione. In questo caso è necessario utilizzare la parola chiave extern, altrimenti il ​​compilatore la considererà una definizione di una variabile locale, che ha un ambito, una durata e un valore iniziale diversi. Questa dichiarazione sarà visibile solo all'interno della funzione anziché in tutto il modulo della funzione.

Ora ripeto ancora una volta definizione di extern che dice "variabile esterna è una variabile DEFINITO di fuori di ogni blocco funzionale" (Si prega di leggere attentamente parola data in BOLD). Così, per la Programe Aa avere definizione, ma è solo b dichiarazione così extern cercherà la sua definizione di 'b' che è dato in Programe B .Così stampa dal Programe A è 1 2 .Ora consente di parlare di Programe B che hanno dichiarazione per a e definizione per b quindi è valore priting a da programe A e il valore di b dal file corrente.

+0

Per quanto ne so int a; è sia dichiarazione che definizione e infatti al di fuori di qualsiasi funzione diventa anche inizializzazione con valore 0. int main() int. ( int a; // sia dichiarazione che definizione ... int a = 5; // dà errore definizione multipla di a. } Si può provare lo stesso anche per le variabili esterne. – tapananand

+1

@TapanAn l'inizializzazione predefinita si verifica quando la definizione non è disponibile.Ma nel tuo caso 'a' e' b' sono dichiarati e definiti correttamente, quindi il compilatore non li inizializzerà di nuovo e tutto ciò per evitare errori di definizione multipli. –

+0

Ok, quindi int b; in Prog A potrebbe non essere un'inizializzazione, ma deve essere una definizione, quindi perché int b = 2 nel prog B non causa un errore? – tapananand