Forum: Compiler & IDEs Probleme mit struct und Funktionen (Suche hilft nicht)


von UBoot-Stocki (Gast)


Lesenswert?

Hi,
ich habe ein struct und eine Variable definiert:
1
typedef struct
2
  {
3
    uint8_t sec;
4
    uint8_t min;
5
    uint8_t hour;
6
    uint8_t day;
7
    uint8_t wday;
8
    uint8_t month;
9
    uint8_t year;
10
    uint8_t dls_flag; 
11
    uint8_t leapyear;
12
  } datestruct;
13
  
14
volatile datestruct zeit;

Die Variable übergebe ich an die Funktion "einstellen" die die Elemente 
in zeit füllen soll:
1
 einstellen(&zeit,1);

Das funktioniert auch, allerdings bekomme ich die warning:

warning: passing argument 1 of 'einstellen' discards qualifiers from 
pointer target type

Die Funktion "einstellen" ist so definiert:
1
 void einstellen(datestruct *time,uint8_t dateflag)

Was bedeutet die warning? Wie bekomme ich die weg ?

Gruß

Andreas

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
die warnung kommt daher, dass deine variable "volatile" ist, dein 
funktions-prototyp das "volatile" aber unter den tisch fallen lässt.

lösungen:
entweder das "volatile" in den prototyp mit aufnehmen.

oder bei der variablen-deklaration drauf verzichten.
ich meine mich zu entsinnen, dass man structs ungefährdet drauf 
verzichten kann. weio die eh nicht in register passen. aber kann mich 
auch irren, probiers aus.

bye kosmo

von UBoot-Stocki (Gast)


Lesenswert?

Hi,

im Tutorial steht

"Mit dem Schlüsselwort volatile sagt man nun dem Compiler, dass die 
entsprechende Variable entweder durch andere Softwareroutinen 
(Interrupts) oder durch die Hardware verändert werden kann. "

Was bei mir der Fall ist. Die Elemente der Struktur werden in der 
Interrupt-Routine vrändert.

Was macht denn mein Programm anders,wenn ich die Variable nicht als 
Volatile declariere ?

Gruß

Andreas

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
die frage ist, was der compiler anders macht.

für den compiler ist eine interruptserviceroutine (ISR) etwas seltsames. 
aus seiner sicht wird sie niemals aufgerufen. daher möchte er sie gerne 
wegoptimieren, da sie aus seiner sicht ja sinnlos ist. gleiches gilt für 
variablen, die sich nur in einer ISR ändern. für den compiler ändert 
sich der wert derartiger variablen nicht, da die ISR ja nicht aufgerufen 
werden kann. ergo wird auch hier der rotstift angesetzt. möglich, dass 
die variable komplett wegfällt, oder nur spezielle fälle ihrer 
bearbeitung berücksichtigt werden.
mit "volatile" gibt man dem compiler den hinweis, dass das doch so nicht 
geht.

meine sicht der dinge jdf in kurzfassung

schau mal im forum, die diskussion volatile, structs und arrays gibts 
öfters
bye kosmo

von Karl H. (kbuchegg)


Lesenswert?

Mittels volatile teilt man dem Compiler mit, dass er sich Optimierungen
auf dieser Variablen verkneifen soll.
Dies deshalb, weil es Wege gibt wie sich diese Variable verändern
kann, die dem Compiler verborgen bleiben und die er nicht
einsehen kann.
Kosmos hat das schon so in etwa angesprochen.

Worum gehts konkret?
Der Optimizer eines Compilers hat die Aufgabe, die Laufzeit
eines Programmes zu verringern. Dazu stehen im unter anderem
die Register einer CPU zur Verfügung. Die kannst du dir als
Speicherzellen in der CPU vorstellen, auf die das Programm
besonders schnell zugreifen kann. Nur: Variablen residieren
primär nicht in CPU-Registern sondern werden im Speicher
abgelegt. D.h. der Compiler muss darauf achten, dass er
die CPU Register wieder aus dem Speicher nachlädt, wenn
es eine Chance gibt, dass sich diese Variable verändert hat.

Bsp:

uint8_t a;

int main()
{
  uint8_t b;
  a = 0;
  b = 5;
  ...
  while( a < b )
    b = b - 1;
}

aus Sicht des Compilers gibt es für a keine Möglichkeit, wie
sich der Wert von a innerhalb der while-Schleife jemals ändern
könnte. Für den Optimizer ergibt sich daher die Situation, dass
es ausreichen würde, den Wert von a vor der Schleife in ein
CPU Register zu laden und dort zu belassen. Für ihn ist es völlig
unnötig, jedesmal den Wert von a im Speicher aufzusuchen um den
Vergleich zu machen. Das würde nur unnötig Zeit kosten.

Nun: In dem Moment, in dem Interrupt Funktionen auf der Bühne
auftauchen, ändert sich die Situation: In einer ISR könnte man
sehr wohl den Wert von a ändern. Nur: Wenn der Compiler die main()
Funktion übersetzt, weiss er davon nichts. Innerhalb der while-
Schleife erfolgt kein Aufruf der Interrupt Routine. Daher
berücksichtigt der Compiler die Änderung von a innerhalb der ISR
schlicht und ergreifend nicht, wenn die while-Schleife übersetzt
wird.

Mittels
volatile uint8_t a;
kann man dem Compiler allerdings mitteilen: a wird auf Wegen
verändert, die du nicht erkennen kannst. Da darfst also auf
dieser Variablen keine wie immer gearteten Optimierungen durch-
führen weil du zu den falschen Schlussfolgerungen kommen wirst.

Noch extremer wäre dieser Fall:

int main()
{
  a = 0;

  while( a == 0 ) {
    ... Ausdrücke in denen a nicht verändert wird
  }
}

Die Datenfluss-Analyse wird herausfinden, dass a innerhalb
der Schleife nicht verändert wird. Da a mit 0 vorbelegt wurde
wird der Vergleich zur Schleifensteuerung immer true ergeben.
Wenn der Vergleich aber sowieso immer true ergibt, braucht er
auch nicht gemacht werden. Der Compiler ersetzt also die
while-Schleife ganz einfach mit einer Endlosschleife. Nur:
Innerhalb der while-Schleife gibt es keine Möglichkeit dass
a seinen Wert ändern könnte. Aber die ISR kann das tun! Und
wieder: Der Compiler kann das so nicht erkennen, daher muss
man ihm mit einem volatile weiterhelfen.

von kosmonaut pirx (Gast)


Lesenswert?

wie immer unschlagbar detailliertes fachwissen von K.h.B., echt klasse 
und respekt

von UBoot-Stocki (Gast)


Lesenswert?

Moin,

verstehe ich das richtig:

Das Schlüsselwort volatile verhindert letztendlich "nur", dass die 
betroffenen Variablen und damit zusammenhängende Strukturen wegoptimiert 
werden?

Daraus folgere ich (bei gleichbleibender Optimierungsoption):

Wenn nach dem Compilieren das Programm das tut was es soll, dann brauche 
ich das Schlüsselwort "volatile" nicht ?

Gruß

Andreas

von Andreas K. (a-k)


Lesenswert?

> Das Schlüsselwort volatile verhindert letztendlich "nur", dass die
> betroffenen Variablen und damit zusammenhängende Strukturen wegoptimiert
> werden?

Nein. Sondern dass Zugriffe darauf wegoptimiert werden, weil sich aus 
Sicht des Compilers nichts geändert haben kann.

> Wenn nach dem Compilieren das Programm das tut was es soll, dann brauche
> ich das Schlüsselwort "volatile" nicht ?

Auf dass dir bei jedem Compiler-Update der Adrenalinspiegel entsprechend 
ansteigt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.