Ridefinizione consentita in C ma non in C ++?

Perché questo codice funziona in C ma non in C ++?

int i = 5; int i; // but if I write int i = 5; again I get error in C also int main(){ // using i } 

La definizione provvisoria è consentita in C ma non in C ++.

Una definizione provvisoria è qualsiasi dichiarazione di dati esterni che non ha alcun identificatore di class di memoria e nessun inizializzatore.

C99 6.9.2 / 2

Una dichiarazione di un identificatore per un object che ha campo di applicazione senza un inizializzatore e senza un elemento di class di memoria o con lo statico specifico della class di memoria , costituisce una definizione provvisoria. Se un’unità di traduzione contiene una o più de fi nizioni provvisorie per un identificatore e l’unità di traduzione non contiene alcuna definizione esterna per quell’identi fi catore, allora il comportamento è esattamente come se l’unità di traduzione contenga una dichiarazione di portata di tale identi fi catore, con il tipo composito come della fine dell’unità di traduzione, con un inizializzatore uguale a 0.

Quindi int i è una definizione provvisoria. Il compilatore C combinerà tutte le definizioni provvisorie in un’unica definizione di i .

In C ++ il tuo codice è mal formato a causa della regola della definizione unica (Sezione 3.2 / 1 ISO C ++)

Nessuna unità di traduzione deve contenere più di una definizione di qualsiasi variabile , funzione, tipo di class, tipo di enumerazione o modello.


// ma se scrivo int i = 5; di nuovo ottengo anche l’errore in C

Perché in quel caso non rimane più una definizione provvisoria a causa dell’inizializzatore (5).


Solo per informazione

J.5.11 Definizioni esterne multiple

Potrebbero esserci più di una definizione esterna per l’identificatore di un object, con o senza l’uso esplicito della parola chiave extern; se le definizioni non sono d’accordo, o più di una è inizializzata, il comportamento non è definito (6.9.2).

Guarda anche questo eccellente post su variabili esterne .

Si chiama definizione provvisoria. È consentito solo in C.

Una definizione provvisoria è qualsiasi dichiarazione di dati esterni che non ha alcun identificatore di class di memoria e nessun inizializzatore. Una definizione provvisoria diventa una definizione completa se viene raggiunta la fine dell’unità di traduzione e non è stata visualizzata alcuna definizione con un inizializzatore per l’identificatore. In questa situazione, il compilatore riserva lo spazio non inizializzato per l’object definito.

Le seguenti affermazioni mostrano definizioni normali e definizioni provvisorie.

 int i1 = 10; /* definition, external linkage */ static int i2 = 20; /* definition, internal linkage */ extern int i3 = 30; /* definition, external linkage */ int i4; /* tentative definition, external linkage */ static int i5; /* tentative definition, internal linkage */ int i1; /* valid tentative definition */ int i2; /* not legal, linkage disagreement with previous */ int i3; /* valid tentative definition */ int i4; /* valid tentative definition */ int i5; /* not legal, linkage disagreement with previous */ 

Il C ++ non supporta il concetto di una definizione provvisoria: una dichiarazione di dati esterna senza uno specificatore di class di memoria è sempre una definizione.

Da qui: definizioni provvisoria

Per comprendere meglio la definizione provvisoria, segui questo