Hallo, ich habe eine Variable, die ich mit utoa in einen String wandle und per USART senden möchte. Klappt auch wunderbar. Jetzt habe ich den Umwandlungsbefehl von der UART-Senderoutine in die Main-Routine verschoben (siehe Anhang) und bekomme folgende Warnings: ../sensors_new.c:240: warning: passing argument 1 of 'uart_puts' discards qualifiers from pointer target type ../sensors_new.c: In function 'main': ../sensors_new.c:318: warning: passing argument 2 of 'utoa' discards qualifiers from pointer target type Kompiliere ich ein zweites Mal, sind die Warnings weg. Verändere ich etwas am Programm, sind sie beim ersten Kompilieren da, dann wieder weg. Ist das etwas, worüber ich mir Sorgen machen muss?
Die Variable "conversion_buffer" war vorher als "char" deklariert. Bei der Änderung habe ich diese dann als globale Variable "volatile char" deklariert (siehe Anhang im ersten Post). Wenn ich sie nicht als "volatile" deklariere, sind die warnings weg, allerdings muss ich sie doch als "volatile" deklarieren, da zwei Routinen auf die Variable zugreifen müssen, oder?
Dass die Warnungen beim zweiten Kompilieren weg sind, leuchtet ein. Dafür sorgt nämlich dein Makefile. Das passt auf, dass auch nur dann neu kompiliert wird, wenn sich was an der Datei geändert hat (Zeitpunkt der letzten Änderung). Unter "qualifiers" versteht man diese Dingers vor den Variablen ("const", "volatile", "static" usw.).
Nachtrag: Zum Thema "volatile" oder nicht: Das ist gedacht, um den Optimierer zu knebeln, insofern hast du mit deiner Annahme Recht. Les dazu auch mal die Doku vom Linux-Kernel, da ist ein Essay dabei (Anhang). Um das Problem zu umgehen, musst du casten:
1 | volatile char conversion_buffer[7]; |
2 | |
3 | void send_check(void) { |
4 | ...
|
5 | uart_puts((char) conversion_buffer); |
6 | ...
|
7 | }
|
8 | |
9 | int main(void) |
10 | {
|
11 | ...
|
12 | while(1) |
13 | {
|
14 | if (dt_change == 1); |
15 | {
|
16 | utoa(dt,(char) conversion_buffer,10); |
17 | dt_change = 0; |
18 | }
|
19 | |
20 | send_check(); |
21 | }
|
22 | }
|
Beachte die "(char)"-Casts.
Danke für Deine Antwort. Bin heute schon zu müde, um den Text im Anhang zu lesen, das mache ich dann morgen. Hab das mit dem casten gerade noch schnell probiert, jetzt kommen dafür andere Warnings: ../sensors_new.c:239: warning: passing argument 1 of 'uart_puts' makes pointer from integer without a cast ../sensors_new.c: In function 'main': ../sensors_new.c:317: warning: passing argument 2 of 'utoa' makes pointer from integer without a cast Komisch, dabei habe ich die Casts doch extra eingefügt...Werde morgen mal versuchen da weiter durchzusteigen.
die casts müssen natürlich auf "char *" gehen, du willst ja nur den "volatile" qualifier wegkriegen... also
1 | utoa(dt,(char*) conversion_buffer,10); |
Ich würd allerdings eher das "volatile" bei der Variablendeklaration weglassen, wenn du das an "utoa" übergibst ist das eh sinnlos, ausser du sperrst vor dem utoa Aufruf explizit alle interrupts.
Ja, jetzt sind die Warnings weg. Leider habe ich gar keine Ahnung, was ich da gemacht hab. In C von A bis Z hab ich zu Casting nur gefunden, dass es sich um Typumwandlungen handelt. Hat einer von Euch eine gute Quelle, in der das beschrieben steht? Ansonsten werd ich morgen mal bischen im Internet suchen, da findet sich bestimmt einiges zu der Thematik. Den Text im Anhang habe ich etwas angelesen, da geht es um volatile, aber nicht um casts. So wirklich habe ich das allerdings leider auch nicht verstanden. Gute Nacht! Dennis
Volatile hat übrigens nicht viel mit "global" zu tun. Und für Arrays ist Volatile in der Regel nicht nötig, ich glaube Arrays landen immer im RAM und nicht in Registern (Vielleicht weiss es jemand besser, den "Wissen" ist bekanntlich besser als "Glauben") In Deinem Fall ist das Volatile eh unnötig. Solange sich Interrupt-Routinen und übrige Programteile nicht die selben globalen Variabeln teilen, erkennt der Compiler zuverlässig, wie weit er optimieren darf...
> Volatile hat übrigens nicht viel mit "global" zu tun. Und für Arrays > ist Volatile in der Regel nicht nötig, ich glaube Arrays landen immer > im RAM und nicht in Registern (Vielleicht weiss es jemand besser, > den "Wissen" ist bekanntlich besser als "Glauben") Am besten ist, das volatile einfach trotzdem zu verwenden, denn schaden tut's nicht. Dann braucht man es gar nicht zu wissen, und es besteht nicht die Gefahr, daß eine neue Compilerversion es doch mal anders handhaben könnte.
>Am besten ist, das volatile einfach trotzdem zu verwenden, denn schaden >tut's nicht. Präziser: Wenn Geschwindigkeit und Codegrösse egal sind, dann schadet es nicht...
Es ging mir natürlich um den Fall, wenn man will, daß Zugriffe auf das Array nicht wegoptimiert werden. Da schadet volatile nicht, denn es ist genau dazu da.
Dennis wrote: > Die Variable "conversion_buffer" war vorher als "char" deklariert. Bei > der Änderung habe ich diese dann als globale Variable "volatile char" > deklariert (siehe Anhang im ersten Post). Wenn ich sie nicht als > "volatile" deklariere, sind die warnings weg, allerdings muss ich sie > doch als "volatile" deklarieren, da zwei Routinen auf die Variable > zugreifen müssen, oder? Als volatile erklärt man nur dann Variablen, wenn diese sog. Seiteneffekte haben können, die der Compiler nicht selber ermitteln kann. Beipiel: Du greifst mittels Polling auf eine Variable zu (=warten auf Änderung, nur lesend), die ggf. in einer Interrupt-Routine dann wirklich verändert wird (schreibend). Der Compiler hat von dieser Änderung im Hintergrund (IRQ) keine Ahnung und würde die Warteschleife schlimmstenfalls wegoptimieren. Hier sagt ihm das volatile für eben diese Variable, daß er sie doch ständig so testen muß, wie es der Code vorgibt. Wenn zwei Routinen auf eine Variable ändernd zugreifen, und sie das brav sequentiell tun, ist kein Grund für volatile gegeben. Die Schreiboperation ist beim Beenden der Routine immer vollzogen und eine nachfolgende Routine verwendet den neuen Wert wenn sie aufgerufen wird. Tut eine Routine das im Interrupt und eine im normalen Kontext, nützt einem volatile auch nichts, da braucht man dann andere Mechanismen um atomare Operationen sicherzustellen. Bei Nebenläufigkeit muß man sich einige Gedanken mehr machen. Meistens wendet man dabei aber volatile falsch an, bzw. es ist keine Lösung, sondern nur eine Hoffnung. Jürgen
Peter wrote: > Volatile hat übrigens nicht viel mit "global" zu tun. Und für Arrays > ist Volatile in der Regel nicht nötig, ich glaube Arrays landen immer > im RAM und nicht in Registern (Vielleicht weiss es jemand besser, > den "Wissen" ist bekanntlich besser als "Glauben") Das eine hat mit dem anderen nichts zu tun. Sicher versucht der Compiler zu optimieren, indem er Dinge so lange wie möglich in Registern hält. Darüberhinaus geht es aber noch um echte Code-Optimierung (oder besser "Weg-Optimierung): int bla; void warte(void) { bla = 0; [...] /* tue etwas, aber rühre bla nicht mehr an */ [...] if (bla != 0) /* tue dies */ else /* tue jenes */ } Der komplette Teil von "tue dies" kann vom Compiler verworfen werden, weil er ermitteln kann, daß sich in diesem Kontext "bla" nicht verändert. Würde also eine Interrupt-Routine "bla" verändern, bekäme diese Funktion hier das gar nicht mit. "volatile int bla;" würde dem Compiler genau diesen Seiteneffekt aber mitteilen und der if-Test würde erhalten bleiben und auch "tue dies" hätte eine Chance jemals ausgeführt zu werden. Jürgen
Danke für die ausführliche und verständliche Erklärung!
Hallo Zsammen, ich will das Thema nochmal aufgreifen, weil ich vor dem gleichen Problem stehe. Ich habe versucht, wie oben beschrieben, meine Übergabe zu Casten. if (strncmp ((char *) &gpsmsgbuf[3], "RMC", 3) == 0). Der Compiler meckert nun auch nicht mehr, aber das Programm hängt sich auf sobald ich (anscheinend) öfter bzw an bestimmten Stellen lesend drauf zugreife. Ich habe auch schon probiert das "volatile" zu entfernen. Das klappt so auch ganz gut, ABER ich habe irgendwie die Befürchtung, dass das irgendwann doch Probleme gibt weil ich ja mit der UART-ISR darauf zugreife. Wie gesagt, so klappts bisher (2 Versuche) aber ich frage mich warum der Compiler mein Array dann nicht wegoptimiert. Ich schreibe an keiner anderen Stelle in das Array. MfG, Marten83
Hi Marten83, wieso sollte der Compiler Dein Array wegoptimieren? Er weiß doch nicht, was die strncmp(), die genau dieses Arrary benutzt, damit macht (weil Kontext-Wechsel). Also muss das Array und der Zugriff darauf erhalten bleiben und wird immer dann ausgeführt, wenn es Dein C-Quelltext vorsieht. jbe
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.