2013-01-21 8 views
12

Il seguente codice in C ha un comportamento definito?La rimozione di const da un puntatore a const obbedisce a un aliasing rigoroso in C e si riferisce allo stesso oggetto?

int main() { 
    const int i = 0; 
    return *(int*)(&i); 
} 

Lo chiedo perché 6,5/7 elenca "una versione qualificato di un tipo compatibile con il tipo effettivo dell'oggetto" come alias valido. Ma il tipo effettivo dell'oggetto è const int e non penso che sia una versione qualificata di const int (sebbene sia vero il contrario). Né sono compatibili int e const int (6.7.3/10).

Inoltre, 6.3.2.3/2 indica che è possibile convertire i tipi di puntatore da aggiungendo i qualificatori e che il puntatore risultante è uguale. 6.3.2.3/7 afferma che è possibile convertire qualsiasi tipo di puntatore (quindi è consentito il cast (int*)(&i)). Ma non dice che il puntatore risultante si riferisce allo stesso oggetto o anche che è uguale. Tutto ciò che dice è che può essere riconvertito al tipo originale (in questo caso const int*). Cioè, anche se l'alias è legale, non è chiaro per me che lo standard garantisce che la mia conversione puntatore abbia effettivamente come risultato un puntatore che si riferisce a i.

Quindi, lo standard definisce effettivamente il comportamento del mio codice e, in caso affermativo, dove è definito?

Sono consapevole che il codice funziona in pratica. Ho in mente un'ipotetica (e bizzarra) implementazione su cui non funziona. Potrei chiedere se tale implementazione è conforme allo standard (e se no, quale parte viola), ma non voglio confondere le acque se ci sono altri aspetti in cui la mia implementazione immaginata non riesce a conformarsi. Descriverò l'implementazione se qualcuno pensa che li aiuterà a rispondere alla domanda.

+0

Per il cast ritorna a 'int const *' lo standard è chiaro che il risultato deve essere l'identità. "Altrimenti, una volta convertito nuovamente, il risultato deve essere paragonato al puntatore originale ." –

+0

@JensGustedt: concordato. Questo non aiuta il mio codice, perché il mio codice non lo restituisce mai a 'int const *'. –

risposta

7

è almeno implicava che funziona, da §6.7.3 p5:

Se si tenta di modificare un oggetto definito con un tipo const qualificato attraverso l'uso di un Ivalue con il tipo non-const-qualificato, il comportamento non è definito. Se si tenta di fare riferimento a un oggetto definito con un tipo con qualifica volatile tramite l'uso di un lvalue con tipo non volatile, il comportamento non è definito.

Si noti che per i tipi di volatili qualificato dice riferiscono a, ma per i tipi const qualificato si dice solo modificare, il che implica che un accesso non modifica è OK ("l'eccezione che conferma la regola ").

Mi sembra che tu abbia identificato un difetto nello standard, però.

+0

Penso anche che questo dovrebbe essere un difetto, ma d'altra parte, è implicito che sappiamo come vengono implementate le variabili const. – Spidey

+1

Non sono d'accordo: mentre la const-qualification non rende indefinito l'accesso non modificabile tramite espressioni punteggiate, le regole di tipizzazione valide continuano a essere valide: i tipi con qualifica diversa sono incompatibili (tranne quando si determina la compatibilità dei tipi di funzione in base ai parametri) e le regole sono solo rilassati nella direzione di * qualifica aggiuntiva * – Christoph

+2

@Christoph: concordo che ciò è il risultato di una lettura rigorosa delle regole di aliasing, ma il mio punto è che non penso che questo sia stato l'effetto * voluto *, perché renderebbe il paragrafo normativo che ho citato del tutto discutibile, e non spiega perché una diversa formulazione è stata usata per const-and volatile- in esso. – caf

Problemi correlati