Forum: Compiler & IDEs Statemachine, Funktionszeiger oder Variable


von Andreas W. (Gast)


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?

von yalu (Gast)


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.

von Andreas W. (Gast)


Lesenswert?

ok
1
void (*Funktion)(void);
2
3
void machewas1()
4
{
5
  Funktion = machewas2;
6
}
7
void machewas2()
8
{
9
  Funktion = machewas3;
10
}
11
void machewas3()
12
{
13
  Funktion = machewas1;
14
}
15
16
void machs()
17
{
18
  Funktion();
19
}

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

von yalu (Gast)


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.

von John G. (johngo)


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...

von StinkyWinky (Gast)


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.

von Oliver (Gast)


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

von Thomas W. (thomas_v2)


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.

von StinkyWinky (Gast)


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.

von Gast (Gast)


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.

von Kai G. (runtimeterror)


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.

von Kai G. (runtimeterror)


Lesenswert?

>Wo wendet ihr eigentlich Funktionszeiger an?

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

von Oliver (Gast)


Lesenswert?

>Wo wendet ihr eigentlich Funktionszeiger an?

z.B. in einer statemachine :-)

Oliver

von StinkyWinky (Gast)


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von yalu (Gast)


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
;-)

von Andreas W. (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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...

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.