ich habe ein Verständnisproblem zum vordefinieren von lokalen Variablen in Funktionen. Vor einiger Zeit entstand hier mit Hilfe einiger aus dem Forum bei mir folgende Funktion.
boolean blinkms(int Millis, boolean rel){
static unsigned long PreviousMillis;
static boolean back;
unsigned long CurrentMillis = millis();
if(CurrentMillis - PreviousMillis >= Millis) {
// save the last time you blinked the LED
PreviousMillis = CurrentMillis;
if(back == false || !rel) back = true;
else back = false;
}
return back;
}
Das funktioniert auch soweit. Ich finde es aber unsauber, da im ersten Aufruf der Funktion die Variable PreviousMillis irgendwas sein kann. Meine Frage ist, wenn ich jetzt die Variablendeklaration umändere in folgendes:
static unsigned long PreviousMillis = 0;
static boolean back = flase;
unsigned long CurrentMillis = millis();
Funktioniert das ganze dann novh, oder wird bei jedem zyklischen Aufruf PreviousMillis und back auf 0 bzw false geschrieben?
lokale static Variablen werden wie globale Variablen automatisch mit 0 initialisiert. Nur lokale nicht-static Variablen müssen explizit initialisiert werden.
im Netz steht das auch überall so wie Du schreibst. In meinen Büchern ist das zugegeben allgemein formuliert. Die reden pauschal von Variablen. Ist dennoch für mich nicht logisch warum der Compiler da nochmal unterscheiden soll. Ergibt eigentlich keinen Sinn.
Zum Spass habe ich mal folgenden Code erzeugt und mehrfach resetet, erhalte immer 0.00
Hallo Doc Arduino,
es macht schon Sinn, wenn der Compiler das unterscheidet.
Globale und statische lokale Variablen sind im Prinzip dasselbe. Beide belegen einen fixen Speicherplatz, der bereits beim Start des Programms bekannt ist. Der Unterschied liegt einzig im syntaktischen Scope der Variablen. Das System stellt dabei einfach sicher, dass der zugewiesene Bereich mit 0 initialisiert ist.
Nicht statische lokale Variablen funktionieren vollständig anders. Sie werden jedes Mal neu erzeugt und am Ende der Funktion wieder freigegeben. Dabei ist nicht sichergestellt, dass bei jedem Aufruf derselbe Speicherbereich zugewiesen wird. Bei so kleinen Systemen wie dem Arduino wäre es nicht sinnvoll, bei jeder Erzeugung einer lokalen Variablen noch ein Initialisierungscode auszuführen, der vielleicht gar nicht gebraucht würde. Theoretisch wäre es möglich, dass der Optimizer erkennt, ob der Programmierer eine eigene Initialisierung macht und nur dann die automatische Initialisierung weglässt.
Dein Testprogramm ist nicht sehr aussagekräftig, da du in diesem sehr wenig machst. Du solltest in eigenen Funktionen weitere lokale Variablen erzeugen und diese auch Werte geben. Damit erhöhst du die Wahrscheinlichkeit, dass der Speicherbereich deiner Testvariablen irgendwann mal mit Werten gefüllt werden.
Auch wenn alle Tests auf eine automatische Initialisierung hinweisen sollten, würde ich mich strikt an die Dokumentation halten. Initialisierungsfehler sind schwer zu finden und können einem zur Verzweiflung treiben.
Doc_Arduino:
Zum Spass habe ich mal folgenden Code erzeugt und mehrfach resetet, erhalte immer 0.00
Das ist Zufall. In Visual C++ sieht es anders aus. Je nachdem ob man die Variablen als short, int, long oder double definiert steht da was anderes drin, wenn man sie mit dem Debugger betrachtet. Allerdings bei allen Variablen des gleichen Datentyps das selbe. Und wenn man das Programm laufen lässt kommt ein "Run-Time Check Failure".
Aber wie gesagt auch auf dem Arduino solltest du dich nie darauf verlassen. Gerade weil es standardmäßig keine Warnungen gibt und das Programm bei Fehlern einfach weiterläuft.
Ich habe in meinem Sketch in den Funktionsparametern lokale Variablen drin. Die werden von der IDE rot dargestellt. Das bedeutet, die sind als Schlüsselwörter der IDE schon von woanders her bekannt.
Solange die lokal bleiben dürfte doch nichts passieren?
Wenn ich solche Variablen die rot dargestellt werden global verwenden sollte, dann gibt ein durcheinander. Richtig?
Ich habe in meinem Sketch in den Funktionsparametern lokale Variablen drin. Die werden von der IDE rot dargestellt. Das bedeutet, die sind als Schlüsselwörter der IDE schon von woanders her bekannt.
Solange die lokal bleiben dürfte doch nichts passieren?
Wenn ich solche Variablen die rot dargestellt werden global verwenden sollte, dann gibt ein durcheinander. Richtig?
Falsch.
Vordefineirte Schlüsselwörter dürfen nicht verwendet werden. ( in Einzelfällen schon, aber besser ist es gar nicht damit anzufangen)
Grüße Uwe
@Doc_Arduino: Vorsicht mit solchen Tests, was auf nicht vorbelegten Variablen steht. Mir sind aus der Industrieautomatisierung mehrer Fälle bekannt, wo nicht sauber definierte Variablen über Jahre(!!!!!) keine Probleme machten, um dann plötzlich von heute auf morgen mit sinnlosen Werten dahrerkamen. Deshalb auch meine Frage überhaupt zu diesem Thema, da ich vor so etwas den Horror habe.
Danke für die Warnung.
Ich frage solange bis ich es verstanden habe, auch wenn es manchmal länger dauert, weil ich es ganz genau wissen möchte. Ich gebe mich sehr selten mit Aussagen zufrieden wie "mach das so, weil das so ist". Das wäre nur die Schnellbesohlung. Bringt auf lange Sicht jedoch sehr wenig. Hintergrundwissen ist laut meiner Meinung nach sehr wichtig. Egal in welchen Bereich im Leben.
Das definieren der verschiedenen Variablen habe ich verstanden und mach das jetzt auch streng nach den Antworten hier. Da sollte nichts mehr schief gehen.
Das mit dem Nachfragen und verstehen sehe ich genauso. Und solche essentiellen Dnge wie Variablen definieren und vorbelegen wird in Einsteigerbüchern leider viel zu kurz und zu schwammig behandelt. Deshalb frage ich da auch immer wieder nach. Und hier gibt es ja auch immer nette Menschen, die einem die Hintergründe erläutern.