2012-03-22 3 views
7

Ho appena incappato in un comportamento che mi ha sorpreso:Utilizzo della variabile appena dichiarata nell'inizializzazione (int x = x + 1)?

Quando si scrive:

int x = x+1; 

in C/C++ - programma (o anche di più l'espressione che coinvolge il recente creazione x variabile complessa) la mia gcc/g ++ compila senza errori. Nel caso precedente X è 1 in seguito. Si noti che non vi è alcuna variabile x nell'ambito di una precedente dichiarazione.

Quindi mi piacerebbe sapere se questo è un comportamento corretto (e potrebbe anche essere utile in alcune situazioni) o solo una particolarità del parser con la mia versione gcc o gcc in generale.

BTW: La seguente non funziona:

int x++; 
+0

Credo x è sempre inizializzato a 0 da gcc, ma non si può fare affidamento su questo comportamento come la norma non chiede questo. Può succedere che in alcuni sistemi la spazzatura. – vidit

+0

@EdHeal: No Non avevo abilitato gli avvisi e non --ansi, ma entrambi non cambiano la situazione (nessun avviso emesso) –

+1

C'è un uso correlato, legale (ma inusuale): 'Node simpleGraph = Node (& simpleGraph) ; 'per creare un grafico con un nodo collegato ciclicamente a se stesso. O ancora più strano, 'int x = sizeof (x);'. – MSalters

risposta

16

Con l'espressione:

int x = x + 1; 

la variabile x viene all'esistenza al cartello =, che è il motivo per cui si può utilizzare sul lato destro della strada. Con "viene all'esistenza", intendo che la variabile esiste ma deve ancora essere assegnata un valore dalla parte inizializzatore.

Tuttavia, a meno che non si inizializzi una variabile con durata di archiviazione statica (ad esempio, al di fuori di una funzione), è un comportamento indefinito poiché lo x che viene fornito ha un valore arbitrario.

C++ 03 ha questo da dire:

Il punto di dichiarazione per un nome è subito dopo la sua completa dichiaratore (clausola 8) e prima della sua inizializzazione (se presente) ...

Esempio:
int x = 12;
{ int x = x; }
Qui il secondo x viene inizializzato con un proprio valore (indeterminato).

In questo secondo caso c'è praticamente quello che hai nella tua domanda.

+0

"nasce" sembra un po 'vago.Penso che sia già dichiarato prima di '=', altrimenti il ​​compilatore si lamenterebbe dell'uso di un identificatore sconosciuto. Ma l'inizializzazione avviene naturalmente al '='. – hirschhornsalz

+0

@drhirsch, non penso che sia vago affatto, ho aggiunto il bit nello standard che lo afferma. – paxdiablo

+0

La mia seconda frase nel mio commento è senza senso (o molto male formulata). Mi riferivo alla frase "entra in vigore", che usi come "punto di dichiarazione". Potrebbe essere inteso come "punto di inizializzazione", che sarebbe sbagliato. – hirschhornsalz

8

Non è, è un comportamento indefinito .

Si sta utilizzando una variabile non inizializzata - x. Otterrai 1 per pura fortuna, tutto potrebbe accadere.

FYI, in MSVS ottengo un avvertimento:

Attenzione 1 avvertimento C4700: variabile locale non inizializzata 'i' usato

Inoltre, in fase di esecuzione, ottengo un'eccezione, così non è sicuramente sicuro.

3

Nel primo caso è sufficiente utilizzare il valore già nel punto in memoria in cui si trova la variabile. Nel tuo caso questo sembra essere zero, ma può essere qualsiasi cosa. L'uso di un tale costrutto è una ricetta per il disastro e per i bug difficili da trovare in futuro.

Per il secondo caso, si tratta semplicemente di un errore di sintassi. Non puoi mescolare un'espressione con una dichiarazione di variabile come quella.

5
int x = x + 1; 

è fondamentalmente

int x; 
x = x + 1; 

Avete appena stato fortunato ad avere 0 a x.

int x++; 

tuttavia non è possibile in C++ a livello di parser! Il precedente potrebbe essere analizzato ma era semanticamente sbagliato. Il secondo non può nemmeno essere analizzato.

-1

Questo comportamento non è definito e il compilatore dovrebbe almeno emettere un avviso. Prova a compilare usando g++ -ansi .... Il secondo esempio è solo un errore di sintassi.

+0

-ansi non cambia la situazione :) –

3

La variabile è definita da "=" on, quindi è valida e quando è definita globalmente, è inizializzata come zero, quindi in tal caso viene definito comportamento, in altri la variabile non è stata inizializzata come tale è ancora unitializzato (ma aumentato con 1).
Osserva che non è ancora un codice molto sano o utile.

0

3.3.1 Punto di dichiarazione 1 Il punto di dichiarazione per un nome è immediatamente dopo la sua completa dichiaratore (clausola 8) e prima della sua initializer (se presente), ad eccezione di quanto indicato di seguito. [Esempio: int x = 12; { int x = x; } Qui la seconda x viene inizializzata con il proprio valore (indeterminato). -end esempio]

Gli stati di cui sopra in modo e dovrebbe avere valore indeterminato, siete fortunati con 1.

1

Il codice ha due possiblities:

  1. Se x è una variabile locale, è ha un comportamento indefinito, dal momento che usi il valore di un oggetto prima che inizi la sua vita.
  2. Se x ha una durata statica o thread-locale, viene preinizializzato a zero e l'inizializzazione statica lo imposterà in modo affidabile su 1. Questo è ben definito.

si può anche voler leggere my answer that covers related cases, including variables of other types, and variables which are written to before their initialization is completed