www.mikrocontroller.net

Forum: Compiler & IDEs Statemachine, Funktionszeiger oder Variable


Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was findet ihr "schöner", eine Statemachine die mit hilfe von einen 
Funktionszeiger auf die "states" zeigt oder ein switch/case oder if/else 
mit hilfe einer Variable?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> eine Statemachine die mit hilfe von einen Funktionszeiger auf die
> "states" zeigt

Das habe ich nicht verstanden. Ein Funktionszeiger zeigt auf eine
Funktion. Ist dann der Zustand ebenfalls eine Funktion? Wie soll das
gehen?

Bei meinen Statemachines ist der Zustand meist eine Enum-Variable. Ihr
Inhalt wird in einer switsch/case-Anweisung abgefragt, wenn es mehr
als zwei Zustände gibt, sonst in einem if/else.

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok
void (*Funktion)(void);

void machewas1()
{
  Funktion = machewas2;
}
void machewas2()
{
  Funktion = machewas3;
}
void machewas3()
{
  Funktion = machewas1;
}

void machs()
{
  Funktion();
}

Das geht natürlich auch mit Eingangsparametern. zum Beispiel ein Byte 
was vom UART kommt.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt ist klar, wie das gemeint war.

Ja, so geht das natürlich auch. Ich würde sagen, welcher Variante man
den Vorzug gibt, ist Geschmackssache.

Bei der switch/case-Variante können einfache Aktionen direkt in die
case-Abschnitte geschrieben und dadurch einige Funktionsaufrufe
eingespart werden. Außerdem kann die Zustandsvariable zu Debugzwecken
leichter ausgegeben werden, da es sich dabei um einen Integerwert
handelt.

Die Funktionspointervariante dürfte auf vielen Architekturen etwas
schneller sein, insbesondere dann, wenn die einzelnen Aktionen sowieso
schon als Funktionen vorliegen.

Autor: John Go (johngo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde im Normalfall die Variante mit der Statevariablen und dem 
Switch/Case bevorzugen, weil sie, wie @yalu auch schon sagte, leichter 
zu debuggen ist. Und das finde ich gerade bei Statemachines sehr wichtig 
- sie sind so schon schwierig genug. Und der Inhalt von Funktionszeigern 
ist eine Adresse und beim debuggen absolut schwierig zu interpretieren. 
Und, ich will mir das Leben ja leicht machen...

Autor: StinkyWinky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Debuggen kann schon ein Argument sein. Allerdings, falls die 
Statemaschine mit der Zeit wachsen soll, finde ich die Variante mit dem 
Funktionszeiger sehr elegant.
Die Grundfunktion (dort wo normalerweise der State ausgewertet wird) 
bleibt immer gleich, alle State(funktionen) bleiben gleich, neue 
hinzufügen und gut ist.
Eine Statemaschine mit Switch die sich über mehrere Seiten hinzieht ist 
für mich der Horror.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vor allem bei geschachtelten Zuständen ist eine Kombination aus beidem 
auch gar nicht so schlecht. Die Hauptzustände über Funktionszeiger, in 
den Funktionen dann kleine switch/case-Maschinchen, falls erforderlich.

Oliver

Autor: Thomas W. (thomas_v2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
StinkyWinky wrote:
> Das mit dem Debuggen kann schon ein Argument sein. Allerdings, falls die
> Statemaschine mit der Zeit wachsen soll, finde ich die Variante mit dem
> Funktionszeiger sehr elegant.
> Die Grundfunktion (dort wo normalerweise der State ausgewertet wird)
> bleibt immer gleich, alle State(funktionen) bleiben gleich, neue
> hinzufügen und gut ist.

Wenn man für die Variable ein enum verwendt und im switch/case-Ausdruck 
auch die Namen der enums verwendet, lässt sich eine Statemachine auch so 
relativ einfach erweitern:
Enum erweitern, case-Bedingung einfügen und gut ist.

Autor: StinkyWinky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hast Du absolut recht. Wenn das Konzept der SM gut gewählt ist, 
spielt es keine Rolle, ob mit Funktionspointer oder Switch/Enum.

Allerdings habe ich schon mehrere Implementationen mit Switch/Enum 
gesehen, welche ziemlich Spaghetti-artig waren. Mit den Funktionen wird 
man zur Modularität gezwungen, was ich als Vorteil erachte.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo wendet ihr eigentlich Funktionszeiger an?

Wenn man objektbasierend in C programmiert oder die klassische 
Sortierfunktion. Die Beispiele kenne ich.

Ich meine, bei der alltäglichen Programmierung in C.

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Variante mit den Funktionszeigern kannte ich gar nicht, wäre aber ab 
sofort mein Favorit :) ... zumindest für die Fälle, wo sich das anwenden 
lässt.

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wo wendet ihr eigentlich Funktionszeiger an?

Zwar nicht in C aber ich verwende die gerne für Event-Handling.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wo wendet ihr eigentlich Funktionszeiger an?

z.B. in einer statemachine :-)

Oliver

Autor: StinkyWinky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ich (nebst SM) schon eingesetzt um zwischen verschiedenen 
Regelalgorithmen umschalten zu können. Auch für Callbacks schon benützt.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ein Callback-Funktion ist das häufigste Anwendungsbeispiel ;)
http://de.wikipedia.org/wiki/R%C3%BCckruffunktion

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wo wendet ihr eigentlich Funktionszeiger an?
> ...
> Ich meine, bei der alltäglichen Programmierung in C.

Etwas Alltägliches sind Funktionszeiger in C nicht. Aber ab und zu
sind die Dinger schon ganz praktisch. Beispiele:

- Kommandozeileninterpreter: Eine Tabelle enthält für jedes Kommando
  den Namen, einen Zeiger auf die Funktion, die das Kommando ausführt
  und ggf. noch ein paar Zusatzinformationen. Man kann dann den
  Kommandonamen mittels einer Schleife (oder ggf. auch mit einem
  effizienteren Suchalgorithmus) suchen lassen und ruft anschließend
  die zugehörige Funktion über den Zeiger auf. Die Alternative wäre
  eine längere und nicht besonders schöne If-Elseif-Anweisung.

  So etwas Ähnliches wird hier (Datei evalf.cpp, Methode
  Eval::function) bei der Auswertung von arithmetischen Ausdrücken
  gemacht, um in eine größere Anzahl unterschiedlicher mathematischer
  Funktionen (sin, cos, tan usw.) zu verzweigen

    Beitrag "Re: Weis jemand, wie man mathematische Ausdrücke in C++ auswert"

- Ich hatte einmal einen Minicompiler geschrieben, der als String
  vorliegende mathematische Funktionen (z.B. 3*x+sin(x)) direkt in
  optimierten Maschinencode umsetzt und diesen in ein Byte-Array
  schreibt. Über einen Zeiger auf dieses Array, der in einen
  Funktionszeiger gecastet wurde¹, konnte die kompilierte Funktion
  dann beliebig oft mit unterschiedlichen Argumenten für x aufgerufen
  werden (z.B., um die Funktion numerisch zu integrieren, Nullstellen
  zu suchen, Funktionsgraphen zu erstellen usw.).

- Beim Multithreading wird der im Thread auszuführende Code ebenfalls
  üblicherweise als Funktionszeiger übergeben.

So arg viel mehr Beispiele für die Verwendung von Funktionszeigern
fallen mir aber gerade nicht ein. In anderen Programmiersprachen,
insbesondere in Funktionalsprachen, ist die Umgang mit Funktionen
wesentlich ungezwungener als in C. Es ist dort bspw. durchaus üblich,
dass einer Funktion eine oder mehrere andere Funktionen als
Funktionsargumente übergeben werden und der Funktionswert ebenfalls
eine Funktion ist.

¹) Kinners, bitte nicht nachmachen! Heutzutage ist Casten zwischen
Daten- und Funktionszeigern böse. Das dürfen nur noch Betriebssysteme
;-)

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, hab es jetzt mit Funktionszeigern gemacht. Ist aber auch ein relativ 
lineare Statemachine, die einen Ablauf steuert.

Ich finde beide Methoden haben ihre Berechtigung.
Nur gefällt mir die mit den Funktionszeigern persönlich vom C-Code 
besser.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu wrote:

> ¹) Kinners, bitte nicht nachmachen! Heutzutage ist Casten zwischen
> Daten- und Funktionszeigern böse.

Es geht schlicht und einfach auch nicht überall.  Ein typisches
Beispiel ist der AVR.

Allerdings kann man einen generischen Funktionszeiger bauen und den in
einen konkreten Zeiger casten, da alle Funktionszeiger ineinander
umwandelbar sind.  Außerdem könnte man natürlich noch einen
Funktionszeiger alternativ zu einem Datenzeiger in eine union legen...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.