Domanda

La domanda è nata nei commenti di una risposta alla domanda Il tipo bool C/C++ è sempre garantito come 0 o 1 quando viene convertito in int?

Il codice in questione alloca un array (locale) di bool senza inizializzare il loro valore.

const int n = 100;
bool b[n];

Chiaramente i valori in b sono indeterminati.

Alcuni commentatori hanno ritenuto che la lettura, ad es. b[0] era un comportamento indefinito.Questo è indicato ovunque nello standard C++?Io sono ancora convinto del contrario:

  1. È chiaramente allocato spazio di archiviazione e l'inizializzazione del tipo bool fondamentale è completa, poiché non dispone di un costruttore.Quindi non è certamente la stessa cosa che dereferenziare un puntatore non inizializzato o chiamare metodi/operatori cast su oggetti non banali non inizializzati.Questi casi specifici sembrano essere coperti dalla norma.

  2. Il comportamento è infatti indefinito in C: Cosa succede a una variabile dichiarata e non inizializzata in C?Ha un valore? e alcuni intervistati sembrano confondere le due cose.

  3. Nell'ultima bozza di C++0x non riesco a trovare alcuna definizione di valore indeterminato soprattutto nessuna definizione che consenta di accedere a tale valore per attivare una trappola del processore.In effetti, Bjarne Stroustrup non è sicuro di quale possa essere un valore indefinito: http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

È stato utile?

Soluzione

Sì, formalmente una conversione rvalue di valore indeterminato è UB (tranne che per unsigned char, originariamente ho scritto "e varianti", ma mi sembra di ricordare le rivolge formali per 1 complemento firmato char dove forse meno 0 potrebbe essere utilizzato come valore di trap)

Sono troppo pigro per fare il punto di ricerca standard per voi e anche per pigro per cura di downvotes per che

Tuttavia, in pratica solo un problema su (1) architetture arcaiche, e forse sistemi (2) a 64 bit.

Modifica : oops, ora mi sembra di ricordare un post di blog e associati Relazione difetto su UB formale per l'accesso ai char indeterminato. quindi forse dovrò controllare in realtà lo standard, + DR ricerca. Argh, che dovrà essere seguito poi, ora caffè!

EDIT2 : Johannes Schaub è stato così gentile da fornire questo link alla domanda SO in cui è stato discusso che UB per l'accesso ai char. Quindi, è lì che mi sono ricordato da! Grazie, Johannes.

applausi e hth.,

Altri suggerimenti

La risposta a questa domanda cambia con l'ultima bozza di lavoro C++1y(N3946) che possiamo trovare Qui.Sezione 8.5 Inizializzatori paragrafo 12 cambia molto da C++03 e C++11 e ora contiene quanto segue (sottolineatura mia):

Se non viene specificato alcun inizializzatore per un oggetto, l'oggetto viene inizializzato predefinito. Quando si ottiene l'archiviazione per un oggetto con durata automatica o dinamica di archiviazione, l'oggetto ha un valore indeterminato, e se non viene eseguita alcuna inizializzazione per l'oggetto, quell'oggetto mantiene un valore indeterminato fino a quando quel valore non viene sostituito (5.17).[ Nota:Gli oggetti con durata di archiviazione statica o del thread sono pari a zero, vedere 3.6.2.— nota finale] Se un valore indeterminato viene prodotto da una valutazione, il comportamento non è definito tranne nei seguenti casi:

e continua elencando alcune eccezioni per tipo di carattere stretto senza segno solo che ho una citazione completa C++1y è cambiato rispetto all'uso di valori indeterminati e comportamento indefinito?.

Quindi nel tuo caso b ha durata di memorizzazione automatica e non è inizializzato e quindi ha valore indeterminato.Quindi valutando b[0] è davvero un comportamento indefinito.

In precedenza ci veniva richiesto di utilizzare la conversione da lvalue a rvalue per dimostrare che questo non era definito, ma da allora è problematico la conversione è sottospecificata.

Si noti che il valore indeterminato è in corsivo in questa sezione e pertanto significa che è stato definito sul posto e quindi ora C++1y definisce effettivamente il termine.In precedenza il termine veniva utilizzato senza definizione, questa è inclusa rapporto sui difetti 616.

In bool, lo standard dice in 3.9.1 tipi fondamentali :

  

I valori di tipo booleano sono o vere o   falso.

Con una nota affermando:

  

Utilizzando un valore booleano in modi descritti   dalla presente norma internazionale come    “undefined” , come esaminando la   valore di una macchina automatica inizializzata   oggetto, potrebbe indurlo a comportarsi come se   non è né vero né falso.

Il fatto che la lettura di un valore indeterminato in genere provoca non definito comportamento non è solo un problema di "teorico". Anche per i tipi in cui tutte le possibili sequenze di bit sono definiti i valori, non deve essere considerato "sorprendente" per i valori indeterminati a comportarsi in modi che differiscono dai valori specificati. Per esempio, se p * tiene indeterminato valore e X non è utilizzato da nessuna parte tranne come illustrato, il codice:

uint32_t x,y,z;
...
x = *p;
if (condition1) y=x;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=x;

potrebbe essere riscritto come:

if (condition1) y=*p;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=*p;

Se il valore di p * è indeterminato, un compilatore non sarebbe proibito dall'avere il codice tra i due "if" modificare il suo valore. Ad esempio, se lo spazio occupato dalle * p era occupata da un "float" prima liberato e ri-malloc'ed, il compilatore potrebbe scrivere che "float" valore compreso tra i due "se" dichiarazioni di cui sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top