volatile
-
In einem Programm habe ich eine Zuweisung in ein Array, das in den adressierbaren Speicher eingeblendet wird. Über dieses Array kann ich also Peripherie ansteuern, das funktioniert jedoch nur exakt mit dieser absoluten Adresse. Nun möchte ich eine Zuweisung machen das ganze sieht in etwa so aus:
void zuweisung(char channel){ char i, *p8; . . . p8 = (char*) 0x80; /* Hier feste Adresse notwendig! */ for(i = 0; i < 15; i++) p8[i] = channel; . . . }
Der Zeiger zeigt also immer auf dasjenige element auf das zugewiesen werden soll. Prinzipiell sollte das auch funktionieren, da ich ja dem Pointer die Adresse zugewiesen habe.
Nun meine Frage:
Kann es durch Codeoptimierung des Compilers passieren, das der code woanders hinoptimiert wird?
Und wäre es dann sinnvoll den Zeiger p mit volatile zu deklarieren damit eine Optimierung dieses Zeigers unterdrückt wird?
Oder habe ich da prinzipiell was nicht verstanden?
-
Theoretisch könnte der Compiler feststellen, dass du den Inhalt dessen, worauf p8 zeigt, gar nicht wieder einliest, und das Schreiben herausoptimieren. Deshalb besser als volatile char * deklarieren. Was du mit "code woanders hin optimieren" meinst, ist mir allerdings unklar.
-
Mit code woanders hinoptimieren meine ich beispielsweise, das variable oft nicht im Ram behandelt werden, sondern z.B. in optimierter Form in CPU-Registern behandelt werden. Das könnte man sogar (fast) erzwingen (Wenn in der Maschine machbar) wenn man eine Variable mit register deklariert.
-
oder du guckst in die manuals zu deinem compiler etc. für solche konstanten adressen gibt's oft macros wie etwaa '#define BLAH *(unsigned char volatile *)0x30'
-
beis schrieb:
Mit code woanders hinoptimieren meine ich beispielsweise, das variable oft nicht im Ram behandelt werden, sondern z.B. in optimierter Form in CPU-Registern behandelt werden.
Was würde das ändern?
btw: ich bezweifle dass der compiler hier das schreiben wegoptimiert, weil er ja nicht wissen kann wohin der Zeiger zeigt. volatile schadet dennoch nicht.
-
Doch sicher weiß er, wohin der Zeiger zeigt. Auf 0x30. Steht doch da.
-
Bashar schrieb:
Doch sicher weiß er, wohin der Zeiger zeigt. Auf 0x30. Steht doch da.
Ja, aber er weiss nicht was dort liegt. Er müsste wirklich sehr agressiv optimieren um das zu 'optimieren', weil er ja absolut keine ahnung hat, wohin geschrieben wird. Die Adresse sagt ihm ja nichts - denn woher soll er wissen was malloc() zurück liefern wird und dadurch zufällig 0x30 genau in so einen Bereich reinfallen wird? oder sonstiges...
sagen wir es so: wenn ich einen compiler geschrieben hätte, würde er soetwas nicht optimieren...
-
Shade Of Mine schrieb:
Ja, aber er weiss nicht was dort liegt. Er müsste wirklich sehr agressiv optimieren um das zu 'optimieren', weil er ja absolut keine ahnung hat, wohin geschrieben wird. Die Adresse sagt ihm ja nichts - denn woher soll er wissen was malloc() zurück liefern wird und dadurch zufällig 0x30 genau in so einen Bereich reinfallen wird? oder sonstiges...
Naja erstmal hat das ja sowieso undefiniertes Verhalten
Vom Standard her musst du bei sowas volatile benutzen, weil nur volatile-Zugriffe zum beobachtbaren Verhalten des Programms gehören.
Und dann weiß der Compiler sehr wohl, wo alles liegt. Oder besser gesagt, der Linker weiß es. Auch wo der Heap liegt.
-
Bashar schrieb:
...der Linker weiß es. Auch wo der Heap liegt.
bei dieser festen adresse ist wohl kein heap gemeint. eher so'n memory-mapped register von irgend 'nem chip oder sowas
-
net schrieb:
bei dieser festen adresse ist wohl kein heap gemeint. eher so'n memory-mapped register von irgend 'nem chip oder sowas
Schon klar, du hast es wohl genau verkehrt rum verstanden.
-
p8 = (volatile char*) 0x80; /* Hier feste Adresse notwendig! */ for(i = 0; i < 15; i++) p8[i] = channel;
"volatile char*" bedeutet Zeiger auf fluechtige "char".
"volatile" ist das einzige Konstrukt in C, das es ermoeglicht, dem Compiler mitzuteilen, dass es die Daten nirgendwo cachen darf, z.B. in Registern.
"volatile" wurde exakt fuer diesen Zweck erfunden: memory mapped I/O.
volatile unsigned char* ioaddr1 = (volatile unsigned char*) 0X12345;
-
Power Off schrieb:
"volatile" wurde exakt fuer diesen Zweck erfunden: memory mapped I/O.
auch bei multithreading und interrupt-routinen ist es von unschätzbarem wert