Verschachtelte (Unter)Funktionen

Guten Morgen liebes Forum!

Ich hab ein kleines Verständnisproblem und leider auch keine Ahnung, welchen Suchbegriff ich bei Google angeben soll. Zumindest habe ich nicht das gefunden, was ich gesucht habe.

Darum hier meine Frage (die ich hoffentlich halbwegs verständlich stelle... :sweat_smile: ):

Wenn ich Funktionen ineinander "verschachtelte", welche Zeile ruft der Arduino als nächstes auf?

Um es etwas bildlicher zu erklären:

int Zahl1 = 0;
int Zahl2 = 0;
int Zahl3 = 0;

void setup() 
  {
  Serial.begin(9600);
  }

void loop() {
  Serial.println(Zahl1);
  Serial.println(Zahl2);
  Serial.println(Zahl3);
  Funktion01();
  Funktion03();
}

void Funktion01()
  {
  Zahl1++;
  Funktion02()
   }

void Funktion02()
  {
  Zahl2++;
  }
  
void Funktion03()
  {
  Zahl3++;
  }

Nochmal genauer gefragt: Wenn ich vom loop aus die Funktion01 aufrufe - und dann von Funktion01 die Funktion02, wo arbeitet der Arduino dann weiter? Ruft er die nächste Zeile in Funktion01 auf oder den Loop?

//Edit: Ausdrucksweise korrigiert

Immer wieder rückwärts in der Aufrufreihenfolge.

Das sind übrigens keine verschachtelten loops. Bitte passe die Überschrift an. Nur auf die Überschrift bezogen wäre die Antwort: Geht nicht.

Gruß Tommy

Tiff48317: Geht er in Funktion01 zurück oder ins Loop?

Nach Funktion01 zurück.

Am Ende jeder Funktion steht: Gehe hinter die aufrufende Zeile zurück. Die Rückkehradresse wird auf dem Stack abgelegt. Bei rekursiver Programmierung muß man daher einen Stacküberlauf vermeiden.

springt

Das tut mir beim Lesen weh.

Es heißt nicht springen, sondern Funktion aufrufen. Am Ende macht die Funktion ein Return, dahin, wo sie herkommt.

Springen macht das falsche Bild in den Kopf! So entstehen dann solche "Irrtümer".

Tipp: Gutes dickes C++ Buch kaufen, und dann auch lesen.

Wieso soll er ausgerechnet direkt nach loop() springen?

(Mal abgesehen von Compiler-internen Optimierungen, die merken, dass das ganz ohne Funktionsaufrufe besser geht)

void setup() {
  Serial.begin(9600);
  // Hier geht es weiter, wenn der controller aus Serial.begin() zurückkommt.
  Serial.println("Was sonst?");
}

Zu Tommys “geht nicht”

void loop2() {
  Serial.print("Hier bleibe ich ");
  delay(100); // Damit man aufmerksam mitlesen kann
}
void loop() {
  while (true) {
     loop2();
     Serial.println("für immer!");
  }
}

Das geht zwar, hat aber den Nachteil, dass alles nach der vorletzten } nie ausgeführt würde.
Auch loop() würde nie beendet, und das wäre ganz dumm :slight_smile:

Vielen lieben Dank für die superschnelle Antwort! Wie wäre die Überschrift denn korrekt? Ich hab den Verdacht, wenn ich das weiß, kann ich das sogar bei Google hust...

Tommy56: Immer wieder rückwärts in der Aufrufreihenfolge.

Das sind übrigens keine verschachtelten loops. Bitte passe die Überschrift an. Nur auf die Überschrift bezogen wäre die Antwort: Geht nicht.

Gruß Tommy

Verschachtelte Funktionen ist schon ok.

Gruß Tommy

Erst wenn man die Antwort kennt, kann man die Frage richtig stellen. :)

Da bist du jetzt angekommen. Glückwunsch.

Sogar ein Hinweis zu rekursiven Aufrufen kam schon. ("Geht, Bringt nichts, Vorsicht")

("Geht, Bringt nichts, Vorsicht")

Wenn man die Rekursion in die Compilezeit verlagern kann, entschärft das deutlich.

michael_x: Zu Tommys "geht nicht"

void loop2() {
  Serial.print("Hier bleibe ich ");
  delay(100); // Damit man aufmerksam mitlesen kann
}
void loop() {
  while (true) {
     loop2();
     Serial.println("für immer!");
  }
}

Das geht zwar, hat aber den Nachteil, dass alles nach der vorletzten } nie ausgeführt würde. Auch loop() würde nie beendet, und das wäre ganz dumm :)

Hinweis: loop() != loop2()

Gruß Tommy

Hi

Die while(1) innerhalb loop() hat den Vorteil, daß intern nicht von loop() zurück (nach main() ) gesprungen wird, um dort die Funktion serialEvent() aufzurufen, bevor wieder loop() ausgeführt wird. 'Springen' im Sinne von CALL und RETURN. Wenn's auf jede noch so kleine gesparte Zeit ankommt (und man auf serialEvent() verzichten kann), vll. im Hinterkopf merken.

MfG

serialEvent() wird nur aufgerufen wenn es existiert. Die Funktion ist als "weak" deklariert und es wird vorher abgefragt ob sie definiert ist

(und man auf serialEvent() verzichten kann)

Je nach µC usw. kann da durchaus noch was anderes aufgerufen werden.

z.B. die ESP machen da noch ihr Multitasking, im Schatten der loop()

Ups ;) Dann stört zumindest Keiner mehr ...