Sta leggendo un comportamento indefinito di valore indeterminato?

La domanda è sorta nei commenti di una risposta alla domanda. Il tipo di boolea C / C ++ è sempre garantito da 0 o 1 quando è convertito in type to int?

Il codice in questione alloca una matrice (locale) di bool senza inizializzarne il valore.

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

Chiaramente i valori in b sono indeterminati.

Alcuni dei commentatori hanno opinato che leggere ad esempio b[0] fosse un comportamento indefinito. Questo è affermato ovunque nello standard C ++? Sono ancora convinto del contrario:

  1. È chiaramente allocata memoria e l’inizializzazione del tipo di bool fondamentale è completa, poiché non ha un costruttore. Non è quindi certo 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 dallo standard.

  2. Il comportamento è davvero indefinito in C: cosa succede a una variabile dichiarata non inizializzata in C? Ha un valore? e alcuni intervistati sembrano confondere i due.

  3. Nell’ultima bozza C ++ 0x non riesco a trovare nessuna definizione di valore indeterminato, in particolare nessuna definizione che consentirebbe l’accesso a tale valore per innescare un trap del processore. In effetti, Bjarne Stroustrup non è sicuro di quale possa essere un valore indeterminato: http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

sì, formalmente una conversione di valore di valore indeterminato è UB (eccetto per il unsigned char , originariamente ho scritto “e varianti” ma come ricordo i cater formali per il complemento firmato di 1 in cui probabilmente 0 potrebbe essere usato come valore trap)

Sono troppo pigro per fare la ricerca del paragrafo standard per te, e anche per pigro a preoccuparmi dei downvotes per questo

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

EDIT : oops, ora mi sembra di ricordare un post sul blog e associato Defect Report su UB formale per l’accesso al carattere indeterminato. quindi forse dovrò effettivamente controllare lo standard, + cercare i DR. Argh, dovrà essere più tardi allora, ora caffè!

EDIT2 : Johannes Schaub è stato così gentile da fornire questo link alla domanda SO in cui è stato discusso di quella UB per l’accesso a char. Quindi, è da dove l’ho ricordato! Grazie, Johannes.

evviva e hth.,

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

Se non è specificato alcun inizializzatore per un object, l’object viene inizializzato di default. Quando si ottiene la memorizzazione di un object con durata di archiviazione automatica o dynamic, l’object ha un valore indeterminato e, se non viene eseguita alcuna inizializzazione per l’object, quell’object conserva un valore indeterminato fino a quando tale valore non viene sostituito (5.17). [Nota: gli oggetti con durata di memorizzazione statica o thread sono inizializzati 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 solo per il tipo di carattere stretto senza segno , ho una citazione completa in Has C ++ 1y modificata rispetto all’uso di valori indeterminati e comportamento indefinito? .

Quindi nel tuo caso b ha una durata di archiviazione automatica e non è inizializzato e quindi ha un valore indeterminato. Quindi valutare b[0] è in effetti un comportamento indefinito.

Precedentemente ci è stato richiesto di utilizzare la conversione da lvalue a rvalue per dimostrare che questo non era definito, ma ciò è problematico in quanto la conversione è sottodimensionata .

Si noti che il valore indeterminato è in corsivo in questa sezione e quindi significa che è stato definito sul posto e quindi ora C ++ 1y definisce effettivamente il termine. Precedentemente il termine era usato senza una definizione, questo è coperto nel rapporto sui difetti 616 .

In bool , lo standard dice sotto 3.9.1 Tipi fondamentali :

I valori di tipo bool sono o veri o falsi.

Con una nota in calce:

L’utilizzo di un valore bool in modi descritti da questo standard internazionale come “non definito”, ad esempio esaminando il valore di un object automatico non inizializzato, potrebbe comportarlo come se non fosse né vero né falso.

Il fatto che la lettura di un Valore Indeterminato generalmente si traduca in un comportamento indefinito non è semplicemente un problema “teorico”. Anche per i tipi in cui tutti i possibili pattern di bit hanno valori definiti, non dovrebbe essere considerato “sorprendente” perché i valori indeterminati si comportino in modi diversi dai valori non specificati. Ad esempio, se * p detiene il valore indeterminato e x non viene utilizzato in nessun luogo eccetto come mostrato, 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, non sarà vietato a un compilatore che il codice tra le due istruzioni “if” ne modifichi il valore. Ad esempio, se la memoria occupata da * p era occupata da un “float” prima che venisse liberata e re-malloc’ed, il compilatore potrebbe scrivere il valore “float” tra le due istruzioni “if” sopra.