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


von uwe (Gast)


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
1
switch (anzahl){
2
case 1:
3
case 2:
4
...
5
}
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!

von (prx) A. K. (prx)


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.

von uwe (Gast)


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

von (prx) A. K. (prx)


Lesenswert?

1
typedef void (*fcnptr_t)(void);
2
3
fcnptr_t tabelle[] = { f1, f2, f3, f4,... }; // lauter Funktionen
4
5
und dann aufrufen mit
6
   tabelle[i]();

von uwe (Gast)


Lesenswert?

okay danke!
ic hwerd mich mal einarbeiten!

von (prx) A. K. (prx)


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.

von P. S. (Gast)


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.

von AVRNeuling (Gast)


Lesenswert?

Dann hast du denn Sinn von switch-case nicht verstanden!
1
unsigned char i = 0;
2
3
if (i == 0)
4
{
5
 // Rufe Funktion 1 auf
6
}
7
else
8
 if (i == 1)
9
 {
10
  // Rufe Funktion 2 auf  
11
 }
12
 else
13
  {
14
    // Rufe Default Funktion auf
15
  }

das ganze analog als switch-case sieht so aus:
1
switch(i)
2
{
3
  case 0: // Rufe Funktion 1 auf
4
         break;
5
  case 1: // Rufe Funktion 2 auf
6
         break;
7
  default:
8
          // Rufe Deault Funktion auf
9
         break;
10
}


Ü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:
1
unsigned char i =0;
2
unsigned char j =1;
3
unsigned char k =2;
4
5
if (i == j)
6
{
7
8
}
9
if (i == k)
10
{
11
12
}

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!
1
typedef void (*fcnptr_t)(void);
2
3
#define MAX_Y 3
4
#define MAX_X 3
5
6
fcnptr_t tabelle[MAX_Y][MAX_X] = { {f00, f01, f02},
7
                                   {f10, f11, f12},
8
                                   {f20, f21, f22}
9
                                 }; // lauter Funktionen
10
11
und dann aufrufen mit
12
   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

von Karl H. (kbuchegg)


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.

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.