mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik anfängerfrage zu switch case!


Autor: uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo, ich möchte in meine code eine switch-case auf eine variable 
ausführen - der compiler schluckt das aber nicht, er besteht auf eine 
Konstante.

wenn ich schreiben
switch (anzahl){
case 1:
case 2:
...
}
funktioniert es, ersetze ich aber "1", "2",... durch "variable_1", 
"variable_2",... geht es nicht mehr!

warum benötigt der compiler hier unbedingt konstanten und kann nicht mit 
variablen arbeiten?

Zweite (und wichtigere) Frage:
wenn ich keine if-else-Anweisung benützen will, wie löse ich das Problem 
mit den variablen? ich hab mal gehört dass if-else-Anweisung deutlich 
länger benötigen als die switch-case, deswegen wäre mir ein switch 
lieber!
Danke!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uwe schrieb:

> warum benötigt der compiler hier unbedingt konstanten und kann nicht mit
> variablen arbeiten?

Weil das so in der Vorgabe C-Standard steht. Wäre andernfalls mehrdeutig 
(könnte mehrfach mit gleichem Wert auftreten).

> wenn ich keine if-else-Anweisung benützen will, wie löse ich das Problem
> mit den variablen?

Garnicht, oder Tabelle mit Zeigern auf Funktionen.

GCC Spezialiät: computed goto, aka Tabelle von Labels. Siehe Manual.

Autor: uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Garnicht, oder Tabelle mit Zeigern auf Funktionen

okay, kannst Du mir dann bitte verraten wie ich das mit den Zeigern 
mache?

sry wenn ich so blöd frage, mit zeigern und pointern habe ich zwar 
bereits gearbeitet, aber prinzipiell bringe ich mir das programmieren 
selbst bei, hab also keinen "großen, weisen Mentor"

Danke!!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
typedef void (*fcnptr_t)(void);

fcnptr_t tabelle[] = { f1, f2, f3, f4,... }; // lauter Funktionen

und dann aufrufen mit
   tabelle[i]();

Autor: uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay danke!
ic hwerd mich mal einarbeiten!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Was oben noch fehlte, um die Variablen ins Spiel zu bringen: Vor dem 
Aufruf für den passenden Inhalt sorgen:
 tabelle[variable_1]= f66;
 tabelle[variable_2]= f77;

Ob das so wirklich sinnvoller als if/else ist wäre im Einzelfall zu 
klären. Wahrscheinlich nicht, oder nur wenn fast alle Fälle Konstanten 
sind.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uwe schrieb:
> hallo, ich möchte in meine code eine switch-case auf eine variable
> ausführen - der compiler schluckt das aber nicht, er besteht auf eine
> Konstante.

Tip: C-Buch kaufen und lesen.

> ich hab mal gehört dass if-else-Anweisung deutlich
> länger benötigen als die switch-case, deswegen wäre mir ein switch
> lieber!

Nach Hoerensagen optimieren kann nur in's Auge gehen.

Tip2: Fang mit dem Optimieren an, wenn du den Rest kannst - und nimm 
solange einfach if.

Autor: AVRNeuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann hast du denn Sinn von switch-case nicht verstanden!

unsigned char i = 0;

if (i == 0)
{
 // Rufe Funktion 1 auf
}
else
 if (i == 1)
 {
  // Rufe Funktion 2 auf  
 }
 else
  {
    // Rufe Default Funktion auf
  }


das ganze analog als switch-case sieht so aus:
switch(i)
{
  case 0: // Rufe Funktion 1 auf
         break;
  case 1: // Rufe Funktion 2 auf
         break;
  default:
          // Rufe Deault Funktion auf
         break;
}


Überleg dir mal wie dein Compiler etwas derartiges wie du es vorhat 
vernünftig (effektiv) in Assembler umsetzen sollst.

Du willst ja so etwas wie:

unsigned char i =0;
unsigned char j =1;
unsigned char k =2;

if (i == j)
{

}
if (i == k)
{

}

Bissl pervers, oder? Oder was passiert, wenn j == k ? Wie schon oben 
geschrieben hast du dann Mehrdeutigkeiten und keine gescheite Logik 
mehr.

Bei meinem Compiler ist es wirklich so, dass ein switch-case effektiver 
(weniger Code) ist, als ein verschachteltes if-else.
Mein Compiler macht das mit Sprungtabellen (ähnlich wie das Beispiel 
oben)

Wobei das für einen Anfänger, der den Sinn von switch-case noch nicht 
begriffen hat, total over-sized ist.

Ein Beispiel für den Einsatz von switch-case sind State-Machines.
Oder ganz einfach wenn EINE Variable mehr als 2 Zustände einnehmen kann, 
dann bietet sich ein switch-case an.

Aber Variablen mit Variablen vergleichen zu wollen ist mit switch-case, 
wie schon erwähnt nicht möglich!

Übrigens ist die Berechnung eines Index in einem Array auch nicht 
"umsonst" ;-)

Und wo bitte hast du damit dein Problem gelöst, dass du Variablen 
effektiv mit Variablen vergleichen willst?

Und wenn ist das nicht mit einem 1-dimensionalen Array zu machen, 
sondern man braucht ein 2-dimensionales!
typedef void (*fcnptr_t)(void);

#define MAX_Y 3
#define MAX_X 3

fcnptr_t tabelle[MAX_Y][MAX_X] = { {f00, f01, f02},
                                   {f10, f11, f12},
                                   {f20, f21, f22}
                                 }; // lauter Funktionen

und dann aufrufen mit
   tabelle[i][j]();


Damit kannst du dann wirklich eine Funktion in Abhängigkeit von 2 
Variablen aufrufen. Bei 3 usw. Variablen wird das ganz umso komplexer.

Aber allein durch die Berechnung des Indizes hast du so viel Overhead, 
dass eine anderes Strategie sicher effektiver wäre.

cheers

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich hab mal gehört dass if-else-Anweisung deutlich
> länger benötigen als die switch-case, deswegen wäre mir ein switch
> lieber!

Die 'deutliche Effektivität' (wobei das Wörtchen deutlich noch zu 
hinterfragen wäre) rührt gerade aus dem Umstand heraus, dass in den case 
Teilen nur Konstante stehen dürfen! Das ermöglicht effizientere 
Bearbeitungstechniken. Fällt die Voraussetzung 'da sind nur Konstanten 
vorhanden' weg, fällt auch die Voraussetzung für die Sprungstrategie weg 
und die effizientere Abarbeitug ist ganz einfach nicht mehr möglich. Da 
dann alledings switch-case in Schwierigkeiten kommen kann (weil mehrere 
case-Zweige auf den selben Wert ausgewertet werden könnten) wird in 
diesem Fall switch-case nicht mehr zugelassen. Vor allen Dingen auch 
deshalb, weil es dann mit einer if-else-if Kette ein perfektes Werkzeug 
gibt, diese Fälle zu handhaben.

Du versuchst hier eine Logik umzudrehen, wobei diese Umkehrung nicht 
zulässig ist.

Und im übrigen gilt: Wenn dein Programm mit einer if/else-if Kette zu 
langsam ist, dann ist es das mit einem switch-case ebenfalls. Das sind 
Mikrooptimierungen, die zwar eventuell ein paar Prozentpunkte bringen, 
die dir aber ein zulangsames Programm nicht um ein paar Größenordnungen 
boosten können. Bei Optimierungen setzt man auf der algorithmischen 
Ebene an, beim Verfahren, und nicht indem man dort ein paar Nanosekunden 
holt und da ein paar Nanosekunden.

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.