2014-11-28 22 views
20

Ich betrachte den folgenden Code ist:Was die Bedeutung von void * volatile * in C++

inline void* interlocked_read_acquire(void* volatile* x); 

und frage mich, warum nicht nur ein volatile void* als Argument. Was ist im Allgemeinen die Semantik oder Definition eines volatile*? Ich mache auch die Annahme, dass Sie den volatile* Qualifier mit einem anderen Typ als void verwenden könnten. Ist das korrekt?

+0

Das gültig scheint, aber ich bin nicht sicher, wie es zu lesen, so dass Deshalb fragte ich. –

+1

Meine Vermutung für den Downvote würde sein, dass jemand nur den Titel der Frage gelesen hat und angenommen hat, dass es eine Frage ohne Forschung darüber ist, was 'void' oder' volatile' isoliert bedeutet. –

+2

@vsoftco sicherlich ist das eher eine Überschätzung (unter Leuten, die dem C++ - Tag sowieso folgen) - "volatile" ist allgemein bekannt und so ist die Bedeutung von einfachen Zeigerdeklarationen, also auch wenn diese spezifische Kombination vorher nicht gesehen wurde ausgearbeitet sein –

Antwort

20

Verwenden cdecl oder clockwise spiral rule C-Stil Erklärungen dechiffrieren:

void* volatile* x 
  • erklärt x als Zeiger auf volatile pointer

für ungültig zu erklären, die aus unterschiedlichen ist:

volatile void* x 
  • declare x als Zeiger auf flüchtige Leere
+2

quantdev, macht "volatile void" überhaupt Sinn? Oder macht es in Güssen? – vsoftco

+2

@vsoftco: Es macht Sinn - Sie können hinzufügen, aber nicht 'volatile' während einer' static_cast' entfernen (Sie müssten auch 'const_cast' verwenden), so dass die' volatile void * 'ist' volatile' hilft, versehentlich zu verhindern Beseitigung der Volatilität beim Zugriff auf das Zielobjekt. –

+0

volatile void macht Sinn wenn Sie annehmen, dass eine void * nicht auf eine void verweist, zeigt sie auf etwas mit einem realen Typ, aber Sie wissen nicht welchen Typ. "Volatile void *" bedeutet also "könnte volatile int * sein, könnte volatile double * sein, könnte volatile sein struct * ..." – gnasher729

10

fragen, warum [void* volatile* und] nicht nur ein volatile void* ...?

Sie sind verschiedene Dinge.

  • void* volatile* ist ein Zeiger auf eine volatile (void*) (so dereferencing und die volatile void* Zugriff möglich ist, ohne Casting, aber würden Sie nur geben Sie die Adresse einiger bis jetzt noch nicht spezifiziert, was im Speicher)

  • volatile void* ist ein Zeiger auf einen flüchtigen void (so Sie sich wie zu einer Art volatile int* oder volatile My_Class* vor dereferencing sagen Guss muss)

7

void * ptr1; bedeutet, dass ptr1 ist eine Variable, deren Typ void *. Dieser Typ gibt einen "generischen Zeiger" an - er zeigt auf einen Speicherort, enthält aber keine Typinformationen, was sich an diesem Speicherort befindet.

void * volatile ptr2; bedeutet, dass die variable ptr2 auch ein generischer Zeiger ist, sondern ist auch ptr2volatile. Das Schlüsselwort volatile ist ein cv-Qualifier genannt, und es hat die gleichen Grammatikregeln wie const.

Die Bedeutung eines flüchtigen Variable ist, dass, wenn ein anderer Code ptr2 sagt, kann der Compiler nicht optimieren heraus; er muss den Speicherort lesen oder schreiben, in dem ptr2 gespeichert ist; es muss die Möglichkeit zulassen, dass ein externer Prozess diesen Ort liest oder schreibt.

Schließlich ist void * volatile *x etwas, das auf ptr2 zeigen kann. Zum Beispiel könnten wir void * volatile * x = &ptr2; haben.Wenn wir dann beispielsweise *x = NULL; schreiben, dann hat *x den Typ void * volatile, was die gleichen Auswirkungen hat, wie wir sie für ptr2 betrachtet haben.

Der Compiler würde sich beschweren, wenn Sie den Qualifier, z. void * *y = &ptr2;. Dies liegt daran, dass der Ausdruck *y dann den Typ void * (nicht-flüchtig) hätte, so dass der Compiler Optimierungen durchführen könnte, dies ist jedoch ein inkorrektes Verhalten, da ptr2 diese Optimierungen nicht zulässt. (Sie können erkennen, dass "volatile-correctness" die gleiche Art von const-correctness ist).

-1

flüchtig ist ein Add-on-Eigenschaft können Sie es zuerst entfernen

void* volatile* x 

zu lesen:

void* *x 

Das ist sehr vertraut. Zum Beispiel ein Array von malloc-ed-Speicherzeigern. Und Sie werden nicht verwirrt mit

volatile void* 

die

zu reduziert wird
void* x.