Newsgroup: it.comp.lang.c
Titolo: problema nomi di variabili

Ho un programma composto di più file.
In un file ho una variabile dichiarata fuori dalle funzioni chiamata fd
che mantiene un filedescriptor. In un altro file ho un'altra variabile fd
che tiene un altro descrittore dichiarata allo stesso modo.
Ebbene, ho notato che una delle due sovrascrive l'altra. Perché? Credevo
che lo scope di una variabile globale dichiarata dentro un file fosse
limitata al file stesso e che solo richiamandola con extern fosse
accessibile da altri file. Eppure a quanto pare mi sbagliavo...
Qualcuno mi può spiegare questa cosa? Grazie

 Qualcuno mi può spiegare questa cosa? Grazie
Qualche altro dubbio? :-)
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 Qualcuno mi può spiegare questa cosa? Grazie
Se vuoi che abbia "internal linkage", cioè che sia visibile solo nel
modulo dov'è dichiarato, devi fare precedere la dichiarazione dalla parola
chiave "static".
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Qualche altro dubbio? :-)
sì, scusa, e allora extern che senso ha? Se io dichiaro 
int variabile
in un file .c e in un altro file .c dichiaro di nuovo 
int variabile
Cosa cambia rispetto al caso in cui nel secondo file ci metto
extern int variabile
?

 default è già "external".
La parola extern comunica al compilatore che da qualche parte esiste
una variabile che si chiama pippo e che ha le caratteristiche di un
int e che il programmatore puo' usare pippo all'interno del suo
codice senza che nessuno si lamenti di cio': tutti i riferimenti a
pippo saranno risolti in fase di link.


 ?
Secondo me niente.
Cambia qualcosa se, per esempio, lo metti all'interno di una funzione:
   #include <stdio.h>
   int pippo = 1;
   void pluto (void)
   {
      int pippo = 2;
 
      printf("B: pippo==%d (locale)\n", pippo);
      {
         extern int pippo;
         printf("C: pippo==%d (globale)\n", pippo);
      }
      printf("D: pippo==%d (locale)\n", pippo);
   }
   int main (void)
   {
      printf("A: pippo==%d (globale)\n", pippo);
      pluto();
      printf("E: pippo==%d (globale)\n", pippo);
   }
Questo programma stamperà:
   A: pippo==1 (globale)
   B: pippo==2 (locale)
   C: pippo==1 (globale)
   D: pippo==2 (locale)
   E: pippo==1 (globale)


 Per una variabile dichiarata fuori da una funzione, secondo me a niente.
<CODE file_1.c>
#include <stdlib.h>
void fnc(void);
char* pippoP;
int main(void)
{
   pippoP = malloc(100);
   if(NULL != pippoP)
      fnc();
   return 0;
}
</CODE>
<CODE file_2_errato.c>
#include <string.h>
void fnc(void)
{
   strcpy(pippoP, "It doesn\'t work");
}
</CODE>
Per farlo funzionare, e' necessario aggiungere extern char* pippoP
nel file file_2_errato.c


 extern int variabile?
Se nel secondo file la definisci extern, *devi* averla definita nel 
primo file (o in un'altro modulo). Se non metti extern non è necessario, 
anche se la sua visibilità resta globale (ovvero è visibile anche 
nell'altro modulo).

 pippo saranno risolti in fase di link.
devo quindi pensare che il funzionamento sia legato ad una particolarità
del gcc che accetta di compilare anche senza la presenza della extern?
Strano, perché gli passo -std=c99 -ansi -pedantic quindi non dovrebbe
attivarmi nessuna estensione sua....

 nel file file_2_errato.c
No, è necessario aggiungere la dichiarazione: char* pippoP;
extern avrebbe solo il compito di *obbligare* il linker a cercare la 
definizione in un'altro modulo.

 nell'altro modulo).
mi sembra una spiegazione plausibile e che dia un senso alla parola extern.

 attivarmi nessuna estensione sua....
l'extern e le regole di linkage sono precendenti al C99, dovrebbe
comportarsi cosi anche senza tutti quegli switch. :-)


 nel file file_2_errato.c
Questo mi pare ovvio.
Ciò che sto cercando di dire è che quella parolina "extern" è ridondante:
nel file file_2_errato.c ci puoi anche scrivere semplicemente "char*
pippoP".


 No, è necessario aggiungere la dichiarazione: char* pippoP;
La dichiarazione di pippoP e' in file_1.c


 compilatore.
Su questo invece sbagli tu, IMHO.
E ne sono ancora convinto dopo una veloce rilettura del C99: mettere
l'extern nelle dichiarazioni (non definizioni) a livello di modulo è solo
un idiom, una prassi.
Una prassi da seguire, ben inteso, anche perché rende il codice più
leggibile -- purché non ci si aspetti che cambi qualcosa se l'extern non
c'è.


 un idiom, una prassi.
Penso che la sia stia in questi tremini.
int pippo;
a file scope non e' proprio una definizione, ma una cosiddetta
"tentative definition". Diventa una definition, solo se non vengono
trovata altre "istanze" della stessa variabile.
Questo dovrebbe risolvere i conflitti che provoca la scrittura di
int pippo;
a file scope in due file differenti.
Scrivere invece
int pippo = 3;
a file scope e' una vera definizione e se si incontra un'altra
istruzione di questo tipo in un file diverso viene generato un
errore.


 La dichiarazione di pippoP e' in file_1.c
Il compilatore la vuol vedere. Penso non ci siano dubbi che debba essere 
dichiarata anche in quel modulo.
Il punto è che non è necessario sia extern.

 nel secondo, che succede?
Un potenziale casino.
Ma non ti salva nemmeno extern. Puoi fare:
[file1.c]
int pippo;
[file2.c]
int pippo[30];
senza problemi (in compilazione. A runtime dipende).

 int pippo[30];
intendevo ovviamente: extern int pippo[30];

 Il punto è che non è necessario sia extern.
Comincio a non seguirti.
file1.c
char* pippoP;
.....
file2.c
extern char* pippoP;
....
Questo codice e' corretto e _deve_ venire compilato senza errori
da un qualsiasi compilatore standard.


 da un qualsiasi compilatore standard.
Sto dicendo che *non è necessario* sia extern, come puoi leggere nella 
prima riga di quoting.

 [...]
Sì, a occhio direi che mi torna.


 da un qualsiasi compilatore standard.
Senz'altro. Quello che ti si sta dicendo è che anche questo codice...
   file1.c
   char* pippoP;
   ...
   file2.c
   char* pippoP;
   ...
.. è altrettanto corretto (anche se brutto da vedere) e deve venir
compilato senza errori da un qualsiasi compilatore standard.
E nel programma linkato ci sarà UNA SOLA variabile "pippoP", come ha
notato chi ha iniziato il thread.


 Ma non è che scrivendo "extern" in uno dei due file ti salvi...
Diamine... Mancava una faccina. Una per te :-) e una per Vega :-)


 Mi sa che ti sei perso da solo :P
Si, ma mi capita spesso parlando con te :-)



Dato che ci ho sbattuto il muso giusto settimana scorsa, rimando a colui che
ha illuminato l'intero thread:
news:243iv096pumir2lnb...@4ax.com
int i;
e
extern int i;
Sono entrambe dichiarazioni; la differenza e' che "int i;" verra'
interpretata come *tentative* definition in assenza di una vera definizione
(che sarebbe "int i = QUALCOSA;").
Ciaotutti,
*

    external, internal and none.
Il compilatore non deve dare errore in nessun caso perche` ogni file e` 
compilato separatamente.  Durante la compilazione verra` assegnato un 
tipo, una dimensione, un tipo di linkage ed un nome ad un oggetto (o 
funzione).
Sara` poi il linker a decidere se assegnare ad oggetti dichiarati con le 
stesso caratteristiche la stessa area di memoria, considerandoli lo 
stesso oggetto.  Ma lo standard dice: "can be made to refer", per cui 
non e` obbligatorio.  Alcuni linker si possono comportare come il gcc ma 
un altro potrebbe dare errore (simbolo definito piu` volte).
