Forum: Compiler & IDEs if then toogeln ?


von Roberto (Gast)


Lesenswert?

Hallo

Hätte eine Frage zum Optimieren eines Codes:

Ich möchte, dass ein Wert, nach jedem Aufruf, einmal den Wert annimmt 
und einmal den anderen.
Also Toggeln.

Derzeit mache ich das so:
------------------------------------------
void blinken()
{
if (Flag ==0)
  {
  Flag  = 1;
  PORTB |=(1<<5);      // Led EIN
  goto Loop;
  }

if (Flag ==1)
  {
  Flag= 0;
  PORTB &= ~(1<<5);    // Led Aus
  }
Loop:
x=x;
}
------------------------------------------

Also einmal geht die Led AN, einmal AUS.

Code funktioniert soweit.
Dort wo die Zeile mit x=x; steht, muss ich eine Zeile einfügen(z.B.x=x;)
sonst meckert der Compiler mit:
"error: label at end of compound statement"

Dazu hätte ich ein paar Fragen an Euch:

1.)Darf man aus einer If-Then eigentlich mit Goto rausspringen ?
2.)gibt es einen besseren Weg? effizienteren? wie man das machen könnte?

Würde mich auf eine Antwort freuen :-)
DANKE :-)

l.G. Roberto

von pfff (Gast)


Lesenswert?

1
void blink(void)
2
{
3
    PORTB ^=(1<<5);
4
}

von Dussel (Gast)


Lesenswert?

Erstens: goto sollte man nie benutzen. Es gibt ganz selten Fälle, wo es 
sinnvoll ist, aber du kannst dir einfach merken: Benutze es nicht. Bei 
kleinen Programmen macht das nichts, aber wenn die Programme größer 
werden, wird es sehr schnell unübersichtlich.

Zweitens: pfff hat einen guten Weg gepostet, aber wenn du es mit if 
machen willst, ersetze das goto durch return. Damit wird die Funktion 
beendet (aber bei void kein Wert zurückgegeben). Der Vorteil zu goto 
ist, dass genau definiert ist, dass return nur aus der Funktion 
'rausspringt' und nicht irgendwohin im Programm.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Roberto schrieb:
> 2.)gibt es einen besseren Weg? effizienteren? wie man das machen könnte?

Ein goto brauchst Du nicht, wenn Du ein else verwendest:
1
void blinken()
2
{
3
  if (Flag == 0)
4
  {
5
    Flag  = 1;
6
    PORTB |= (1 << 5);      // Led EIN
7
  }
8
  else
9
  {
10
    Flag = 0;
11
    PORTB &= ~(1 << 5);    // Led Aus
12
  }
13
}

von dunno.. (Gast)


Lesenswert?

1
void blinken()
2
{
3
if (Flag ==0){
4
  Flag  = 1;
5
  PORTB |=(1<<5);      // Led EIN
6
  }else{
7
  Flag= 0;
8
  PORTB &= ~(1<<5);    // Led Aus
9
  }
10
}

manchmal hilft auch tante else weiter...

gotos macht man nicht (unless u know, what ure doing)

wobei pfft natürlich den königsweg geposted hat.

von Karl H. (kbuchegg)


Lesenswert?

Noch eine Variante
1
#define LED_PORT   PORTB
2
#define LED_PIN    5
3
4
void blinken()
5
{
6
  Flag = 1 - Flag;
7
8
  if( Flag )
9
    LED_PORT |= (1 << LED_PIN);
10
  else
11
    LED_PORT %= ~(1 << LED_PIN);
12
}

Aber du siehst schon, abgesehen von der XOR Lösung kreist das alles 
immer irgendwie um die Verwendung von 'else'.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Alle bisherigen Vorschläge unterscheiden sich in der Wirkung vom 
Originalcode, haven also eine andere Wirkung auf Flag oder machen 
implizite Annahmen darüber.

Die XOR-Variante ignoriert das Ändern von Flag komplett, und der Code 
ist nicht mehr atomar.
1
void blinken (void)
2
{
3
    if (Flag == 0)
4
    {
5
        Flag = 1;
6
        PORTB |= (1<<5);     // Led EIN
7
    }
8
    else if (Flag == 1)
9
    {
10
        Flag = 0;
11
        PORTB &= ~(1<<5);    // Led Aus
12
    }
13
}

Wenn es Code aus einem Codegenerator ist, wo goto durchaus nicht 
unüblich ist, dann muss die letzte Zeile mit dem Label so erzeugt werden 
falls kein Statement folgt:
1
    Loop:;

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Alle bisherigen Vorschläge unterscheiden sich in der Wirkung vom
> Originalcode, haven also eine andere Wirkung auf Flag oder machen
> implizite Annahmen darüber.

Die meisten gehen davon aus, daß Flag ein Flag ist, also nur die Werte 0 
und 1 haben kann.

> Die XOR-Variante ignoriert das Ändern von Flag komplett, und der Code
> ist nicht mehr atomar.

Was heißt "nicht mehr"? Der Originalcode ist auch nicht atomar.

von Karl H. (kbuchegg)


Lesenswert?

Johann L. schrieb:
> Alle bisherigen Vorschläge unterscheiden sich in der Wirkung vom
> Originalcode, haven also eine andere Wirkung auf Flag oder machen
> implizite Annahmen darüber.

Natürlich.

Lass uns aber trotzdem davon ausgehen, dass der Fragesteller ein Neuling 
ist und nicht so gefinkelt programmiert, dass die naheliegenden 
Standardannahmen nicht greifen.
Wäre es anders, ist er auf einem Level, das er hier nicht fragen muss.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Johann L. schrieb:
>>
>> Die XOR-Variante ignoriert das Ändern von Flag komplett, und der Code
>> ist nicht mehr atomar.
>
> Was heißt "nicht mehr"? Der Originalcode ist auch nicht atomar.

Doch, im Hinblick auf PORTB schon. Das wird zwar nicht von C 
zugesichert, aber praktisch alle AVR-Anwendungen sind so geschrieben, 
daß PORTB |= 1 zu atomar übersetzt wird als SBI.

Stell dir einfach vor, es gibt eine ISR, die ein anderes Bit von PORTB 
ändert: PORTB |= 1; und die entsprechende IRQ triggert zwischen
1
PORTB ^= 1 << 5
Dann überschreibt das Rückschreiben die Aktion der ISR.

Mit dem Originalcode geschieht so ein Überschreiben nicht.

von avr (Gast)


Lesenswert?

dunno.. schrieb:
> wobei pfft natürlich den königsweg geposted hat.

wurde eigentlich schon mal die Ziel-Hardware genannt?
PORTB lässt auf AVR schliessen.
Neue AVR's togglen Port-Pins wenn man PINx mit 1 beschreibt:
1
    PINB = (1<<5);
woraus
1
    SBI   PINB,5
wird  (je nach Compiler auch nur "bestenfalls werden kann")

von Roberto (Gast)


Lesenswert?

Hallo Leute
Danke für die Schnellen und Zahlreichen Antworten :-)

@pfff
>   PORTB ^=(1<<5);
Zum Toogeln des Portbins ?
Muss ich mir merken! Danke!

Wie befürchtet, seht Ihr mein Beispiel jetzt nur für die Port's.
Bei mir kommt das Flag aber auch zum schalten, für andere Verzweigungen.

@Johann L.
> Loop:;
Interessant! Wieder was gelernt :-)

@Rufus Τ. Firefly  u.a.
An Else hatte ich schon gedacht, kam mir aber irgendwie komisch vor.

Werde das mal durchdenken . Danke!

@Dussel
>Erstens: goto sollte man nie benutzen.

mhhh... Was könnte man den hier sonst verwenden, außer goto ?

//Beispiel Anfang-------------------------

Start:

// Flag wird über einen Timer alle Sekunden auf 1 gesetzt
// nur dann soll das Programm hier EINMAL durchlaufen!



Loop:
if (Flag ==1)
   {
   Flag = 0;
   goto Start;
   }

goto Loop;
// Beispile Ende-----------------------

sehe gerade...... dass könnte man vielleicht auch mit "while" machen?
Aber "goto Start" hätte ich noch drinnen..?!

Bin halt das Basic noch gewohnt ;-) :-(



@Avr
>wurde eigentlich schon mal die Ziel-Hardware genannt
Ist ein Mega8


-----------

Habe für die Flag's, heute mit "switch" probiert.
Geht auch gut und ich komme ohne goto aus .

l.G. Roberto

von Karl H. (kbuchegg)


Lesenswert?

Roberto schrieb:

>> Loop:;
> Interessant! Wieder was gelernt :-)

Vergiss es gleich wieder. Die nächsten 2 Jahre brauchst du keinen 
einzigen goto. Es gibt immer bessere Möglichkeiten.


>>Erstens: goto sollte man nie benutzen.
>
> mhhh... Was könnte man den hier sonst verwenden, außer goto ?

Die Elemente der strukturierten Programmierung!

else ist ein natürliches Element der strukturierten Programmierung. Es 
ist einfach die Vervollständigung der Verzweigung

   if( Bedingung )
     mach was
   else
     mach was anderes

Da ist nichts anrüchiges daran.

> sehe gerade...... dass könnte man vielleicht auch mit
> "while" machen?

Nicht vielleicht. Das macht man ganz sicher mit einem while bzw. 
Kombinationen
1
   while( 1 ) {
2
3
     ....
4
5
     if( Flag == 1 ) {
6
       mach was
7
       Flag = 0;
8
     }
9
   }

> Aber "goto Start" hätte ich noch drinnen..?!

Nein.
Wie gesagt: Wenn du die nächsten 2 Jahre meinst, irgendwo goto brauchen 
zu müssen, dann hast du etwas übersehen. Du 'brauchst' goto mit 
Sicherheit noch nirgends. Ich hab in den letzten 25 Jahren 
professioneller Programmierung nur ein einziges mal ein goto benutzt. 
Und selbst das wurde für rund 10 Jahren ausgebaut und durch etwas 
besseres ersetzt.

von Dussel (Gast)


Lesenswert?

>>Erstens: goto sollte man nie benutzen.
>
>mhhh... Was könnte man den hier sonst verwenden, außer goto ?

Habe ich doch geschrieben: return; . Damit wird die Funktion beendet, 
auch wenn es void ist. Allerdings ist in deinem Fall ein else wirklich 
'angenehmer'.

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
>>> Die XOR-Variante ignoriert das Ändern von Flag komplett, und der Code
>>> ist nicht mehr atomar.
>>
>> Was heißt "nicht mehr"? Der Originalcode ist auch nicht atomar.
>
> Doch, im Hinblick auf PORTB schon.

Aber nur die Zugriffe auf PORTB sind atomar. Das Abfragen des Flags, das 
Ändern des Flags und das Ändern des Ports sind drei separate Aktionen. 
Wenn ich z.B. in einer ISR den Status des Flags abfrage, stimmt der 
nicht unbedingt mit dem des Pins überein.

> Das wird zwar nicht von C
> zugesichert, aber praktisch alle AVR-Anwendungen sind so geschrieben,
> daß PORTB |= 1 zu atomar übersetzt wird als SBI.

Nun machst du selbst Annahmen ähnlich denen, die du vorher bemängelt 
hast. AVR wurde vorher nirgends erwähnt.

Roberto schrieb:
> sehe gerade...... dass könnte man vielleicht auch mit "while" machen?

Entweder
1
while (1)
2
{
3
  // Code
4
}
oder
1
for (;;) 
2
{
3
  // Code
4
}

Letzteres ist in meinen Augen etwas eleganter, aber das ist 
Geschmackssache.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Johann L. schrieb:
>>
>> Das wird zwar nicht von C zugesichert,
>> aber praktisch alle AVR-Anwendungen sind so geschrieben,
>> daß PORTB |= 1 zu atomar übersetzt wird als SBI.
>
> Nun machst du selbst Annahmen ähnlich denen, die du vorher bemängelt
> hast. AVR wurde vorher nirgends erwähnt.

Inzwischen ist klar, daß es sich um einen ATmega8 handelt.

Zumindest ich habe noch keine Anwendung mit avr-gcc gesehen, die davon 
ausgeht, daß

  PORTB |= 1

evtl. nicht atomar übersetzt wird.

Wie gesagt, ich mache diese Annahme auch in meinen (Hobby)-Anwendungen, 
aber bestimmt machen auch einige "Professionelle" diese Annahme, die 
100% davon überzeugt sind, "sauberen" Code zu schreiben — was er mit 
dieser Annahme natürlich nicht ist.

Übrigens bin ich mit der Annahme schon auf die Nase gefallen.

Die Annahme ist durch nichts begründet ausser durch die Erfahrung, daß 
die Sequenz bei aktivierter Optimierung "bisher immer" auf SBI 
abgebildet wurde.

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.