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
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.
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
voidblinken(void)
2
{
3
if(Flag==0)
4
{
5
Flag=1;
6
PORTB|=(1<<5);// Led EIN
7
}
8
elseif(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:
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.
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.
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.
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")
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
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
machwas
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.
>>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'.
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.
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.