Domanda

Lo standard dice che dereferenziazione il puntatore nullo porta ad un comportamento indefinito. Ma ciò che è "il puntatore nullo"? Nel codice seguente, quello che noi chiamiamo "il puntatore nullo":

struct X
{
  static X* get() { return reinterpret_cast<X*>(1); }
  void f() { }
};

int main()
{
  X* x = 0;
  (*x).f(); // the null pointer?  (1)

  x = X::get();
  (*x).f(); // the null pointer?  (2)

  x = reinterpret_cast<X*>( X::get() - X::get() );
  (*x).f(); // the null pointer?  (3)

  (*(X*)0).f(); // I think that this the only null pointer here (4)
}

Il mio pensiero è che dereferenziazione del puntatore nullo avviene solo in quest'ultimo caso. Ho ragione? C'è differenza tra il tempo di compilazione puntatori nulli e runtime in base al C ++ standard?

È stato utile?

Soluzione

Solo il primo e l'ultimo sono puntatori nulli. Gli altri sono risultati di reinterpret_cast e operano quindi su valori di puntatore di attuazione definite. Se il comportamento è indefinito per loro dipende dal fatto che ci sia un oggetto all'indirizzo che fuso a.

Altri suggerimenti

Una costante di espressione intero che restituisce 0 vale come un puntatore nullo, quindi il primo caso è anche dereferenziazione un puntatore nullo.

Un puntatore che è impostato su 0 mediante un calcolo aritmetico non è necessariamente un puntatore nullo. Nella maggior parte delle implementazioni si comporterà nello stesso modo come un puntatore nullo, ma questo non è garantito dalla norma.

C ++ standard (2003) 4.10

4.10 Pointer conversioni

  

1 Una costante puntatore nullo è un   espressione costante integrale (5.19)   rvalue di tipo intero che valuta   a zero. Un puntatore nullo costante lattina   essere convertito in un tipo di puntatore; il   risultato è il valore di puntatore nullo   questo tipo ed è distinguibile da   ogni altro valore di puntatore di opporsi   o puntatore al tipo di funzione. due nullo   i valori dei puntatori dello stesso tipo devono   confrontare uguale. La conversione di un   puntatore nullo costante a un puntatore a   tipo cv qualificato è un singolo   conversione, e non la sequenza di un   conversione puntatore seguita da una   la conversione di qualificazione (4,4).

5.2.10 reinterpretare gettato

  

Nota 64) Conversione di un costante integrale   espressione (5.19) con valore zero   produce sempre un puntatore nullo (4.10),   ma la conversione di altre espressioni   che capita di avere valore zero necessità   non produrre un puntatore nullo.

1) X* x = 0; (*x).f(); Sì. 0 è solidale espressione costante e viene convertito in costante puntatore nullo. Poi puntatore nullo costante può essere convertito nel valore del puntatore nullo.

2) x = X::get(); no, vedi nota 64 a 5.2.10

3) x = reinterpret_cast<X*>( X::get() - X::get() ); no, vedi nota 64 a 5.2.10

4) ( (X ) 0) .F (); Sì.  0 (espressione integrale costante) -> il puntatore nullo costante -> il valore del puntatore nullo.

X* x = 0;
(*x).f(); // the null pointer?  (1)

Credo che questo si qualifica come dereferenziare, anche se f() mai effettivamente utilizza il puntatore this, e non ci sono metodi virtuali in X. La mia reflex è stato quello di dire che questo è un incidente, ma ora che ci penso, io non sono così sicuro.

x = X::get();
(*x).f(); // the null pointer?  (2)

Probabilmente un puntatore non valido. non so se andrà in crash (vedi sopra per il ragionamento).

x = reinterpret_cast<X*>( X::get() - X::get() );
(*x).f(); // the null pointer?  (3)

Il il X::get() - X::get() espressione compilazione? Non pensavo che fosse legale per sottrarre un puntatore da un altro puntatore del genere.

EDIT: D'oh! Certo che è legale. Cosa stavo pensando? Chiaramente, io sono un marrone.

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