Sagen wir, ich habe eine Struktur
%Vor%Wenn ich jetzt eine Instanz dieser Struktur als flüchtig deklariere -
%Vor%Und ich verwende einen flüchtigen Zeiger, um auf diese flüchtige Struktur zuzugreifen.
%Vor%Wenn ich das versuche:
%Vor% Sollte ptrToField
ebenfalls volatil sein? Würde der Compiler wissen, dass prtToField
ohne explizite Erwähnung flüchtig ist, weil auf ihn über ptrToTrial
zugegriffen wird, was flüchtig ist?
Auch wenn es eine Funktion gibt -
%Vor%Wenn wir diese Funktion mit dem oben deklarierten volatilen ptr aufrufen -
%Vor% Ich erhalte einen Fehler: volatile A_t* is incompatible with parameter of type A_t
.
Wenn ich die Funktionsdefinition so ändere, dass volatile
enthalten ist, sehe ich keinen Fehler.
Sollte sich der Compiler nicht auch über den Zeiger p
beschweren - weil p
nichtflüchtig und trialptr->a2
flüchtig ist?
Sollte
ptrToField
auch flüchtig sein?
Mit Ihrer Definition von struct A
wird die Sache, auf die von Mitglied a2
verwiesen wird, nicht als volatile
deklariert. Dass eine gegebene Instanz von struct A
ist volatile
bedeutet, dass ihr Mitglied a2
(der Zeiger) volatile
ist, aber nicht , dass die Sache, auf die es zeigt, volatile
ist. Dies ist der Unterschied zwischen int * volatile
(entspricht dem tatsächlichen Fall) und volatile int *
.
Die Initialisierung, die Sie beschreiben ...
%Vor% ... initialisiert ptrToField
mit dem Wert von Zeiger ptrToTrial->a2
. Da ptrToTrial
auf ein volatile
-Objekt zeigt, muss das Programm den Zeiger (ein Mitglied dieses flüchtigen Objekts) aus dem Hauptspeicher laden. Da die angegebene Sache nicht volatil ist (deklariert wird), gehen jedoch keine Informationen verloren und es besteht kein (neues) Risiko darin, den Typ des ptrToField
-Ziels als eine einfache int
zu deklarieren. Sicherlich hat es keinen Vorteil, ptrToField
selbst als volatil zu deklarieren.
Beachten Sie auch, dass der Name Ihrer Variablen ptrToField
im Widerspruch zu der Verwendung steht, in die Sie sie eingefügt haben. Du initialisierst es nicht, um auf ein Mitglied deiner struct
zu verweisen; Stattdessen initialisieren Sie es als Kopie eines Mitglieds Ihres struct
.
Würde der Compiler wissen, dass
prtToField
ohne explizite Erwähnung flüchtig ist, weil auf ihn überptrToTrial
zugegriffen wird, was flüchtig ist?
Es ist nicht erforderlich, solche Kenntnisse auszuüben, die es möglicherweise hätte, und dieses Wissen würde in jedem Fall wahrscheinlich sehr begrenzt sein. Es weiß, wie diese Variable initialisiert wurde, aber es kann schwierig sein vorherzusagen, wann und wie der Wert danach geändert werden könnte. In jedem Fall sind alle Informationen, die nicht vom deklarierten Typ der Variablen übernommen werden, für die Standard-C-Semantik Ihres Programms nicht relevant.
Sollte sich der Compiler nicht auch über den Zeiger p beschweren - weil p nichtflüchtig ist und trialptr- & gt; a2 flüchtig ist?
Nein, denn obwohl trialptr->a2
flüchtig ist, gibt es kein Problem beim Lesen seines Wertes (zu einem bestimmten Zeitpunkt) und bei der Zuweisung dieses Wertes an eine andere Variable. Objektwerte sind Bitmuster, sie sind weder flüchtig noch nichtflüchtig - das ist eine Eigenschaft ihres Speichers, wie sie über die lvalues kommuniziert werden, auf die sie zugreifen.
Bitte beachten Sie, dass int *a2;
in Ihrem struct A
nicht flüchtig ist.
Also
ptrToField
ist nicht volatile
.
trailFunction(ptrToTrial)
erhält einen Fehler, weil die Funktion trailFunction
A_t *trialptr
erwartet, aber Sie übergeben volatile A_t*
, es ist offensichtlich Kompilierfehler.
Und schließlich:
%Vor% Die Kompilierung ist in Ordnung, weil a2
's int*
ist.
Meine bevorzugte Platzierung ist normalerweise in der Zeigerdeklaration. Auf diese Weise werden alle Register in der Struktur vom Compiler als flüchtig behandelt, und dennoch ist es möglich, andere (z. B. RAM-basierte Schatten) Instanzen der Struktur zu haben, die nicht flüchtig sind, weil sie nicht tatsächlich Hardware-Register sind darunter.
Ich rate Ihnen daher zu verwenden:
%Vor%Schönen Tag noch