Domanda

Si consideri il programma di C composto da due file,

f1.c:

int x;

f2.c:

int x=2;

La mia lettura del punto 6.9.2 della la C99 standard di è che questo programma dovrebbe essere respinta. Nella mia interpretazione della 6.9.2, x variabile è provvisoriamente definito in f1.c, ma questa definizione provvisoria diventa una vera definizione alla fine l'unità di traduzione, e (a mio parere), dovrebbe quindi comportarsi come se f1.c conteneva il int x=0; definizione.

Con tutti i compilatori (e, soprattutto, linker) ho potuto provare, questo non è ciò che accade. Tutte le piattaforme di compilazione Ho provato do collegare i due file di cui sopra, e il valore della x è 2 in entrambi i file.

Dubito che questo accade per caso, o semplicemente come una caratteristica "facile" per fornire in aggiunta a ciò che la norma richiede. Se ci pensate, significa che non v'è il supporto speciale nel linker per le variabili globali che non dispongono di un inizializzatore, al contrario di quelli esplicitamente inizializzato a zero. Qualcuno mi ha detto che la caratteristica linker può essere necessario per compilare Fortran comunque. Sarebbe una spiegazione ragionevole.

Come trovi questo? Altre interpretazioni della norma? I nomi delle piattaforme su cui i file f1.c e f2.c rifiutano di essere collegati tra loro?

Nota: questo è importante perché la questione si verifica nel contesto di analisi statica. Se i due file possono rifiutare di essere collegati su qualche piattaforma, l'analizzatore dovrebbe lamentarsi, ma se ogni piattaforma di compilazione accetta allora non c'è alcun motivo per mettere in guardia su di esso.

È stato utile?

Soluzione

Si veda anche Quali sono le variabili extern in C . Questo è menzionato nello standard C di cui all'allegato informativa J come estensione di comuni:

  

J.5.11 più definizioni esterni

     

Ci possono essere più di una definizione esterna per l'identificatore di un oggetto, con o senza l'uso esplicito della parola chiave extern; se le definizioni non sono d'accordo, o più di uno è inizializzato, il comportamento è indefinito (6.9.2).

Attenzione

Come @ litb sottolinea qui, e come dichiarato nella mia risposta alla domanda con riferimenti incrociati, utilizzando più definizioni per una variabile globale porta ad un comportamento indefinito, che è il senso del livello di dire "tutto può succedere". Una delle cose che può succedere è che il programma si comporta come ci si aspetta; e J.5.11 dice, approssimativamente, "potreste essere fortunati più spesso di quanto si meritano". Ma un programma che si basa su più definizioni di una variabile extern - con o senza la parola esplicita 'extern' - non è un programma strettamente conforme e non garantito per funzionare ovunque. Equivalentemente:. Contiene un bug , che può o non può mostrarsi

Altri suggerimenti

C'è qualcosa che si chiama una "estensione comune" allo standard, in cui definiscono le variabili più volte è consentito fino a quando la variabile viene inizializzata una sola volta. Vedere http://c-faq.com/decl/decldef.html

La pagina collegata dice che questo è il caso di piattaforme Unix - Credo che sia lo stesso per C99 come C89 - anche se forse è stato adottato da altri compilatori per formare una sorta di uno standard de facto. Interessante.

Si tratta di chiarire la mia risposta ad un commento di olovb:

uscita nm per un file oggetto compilato da "int x;". Su questa piattaforma, i simboli sono preceduti da un '_', vale a dire, la variabile x appare come _x.

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

uscita nm per un file oggetto compilato da "int x = 1;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

uscita nm per un file oggetto compilato da "int x = 0;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

uscita nm per un file oggetto compilato da "extern int x;"

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

EDIT: uscita di nm per un file oggetto compilato da "extern int x;" dove x è effettivamente utilizzato in una delle funzioni

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top