Hallo zusammen,
es ist Sonntag, die Sonne scheint und ich beschäftige mich mit einer
vielleicht total banalen Frage.
Ich muß ein Vorzeichen änderbar abspeichern und sehr häufig Werte
inkrementieren. In billig-C-Quelltext sähe das vielleicht so aus:
1
// Einstellungen (nicht const!)
2
// Wie das Vorzeichen gespeichert wird kann ich frei wählen
3
uint8_tconfig_sign=0;// 0 oder 1
4
5
int24_toftgepollteroutine(void){
6
staticint24_tmerker;
7
if(sign)
8
merker+=getincrement();
9
else
10
merker-=getincrement();
11
12
returnmerker;
13
}
oder auch
1
// Einstellungen (nicht const!)
2
// Wie das Vorzeichen gespeichert wird kann ich frei wählen
3
int24_tconfig_sign=-1;// -1 oder 1
4
5
int24_toftgepollteroutine(void){
6
staticint24_tmerker;
7
merker+=config_sign*getincrement();
8
9
returnmerker;
10
}
Das Problem wird ja vermutlich sehr häufig auftreten. Aber gibt es da
für AVR-GCC/ARM-GCC eine Standardlösung?
Viele Grüße
W.T.
Walter Tarpan schrieb:> Das Problem wird ja vermutlich sehr häufig auftreten. Aber gibt es da> für AVR-GCC/ARM-GCC eine Standardlösung?
Prozessor- und Compilerunabhängig gibt es keine Standardlösung, aber
tendentiell ist bei guten Compilern die if/else Variante schneller,
zumindest wenn "sign" sich nicht oft oder gut vorhersagbar ändert.
Konkret: Der AVR multipliziert nicht gern. ARMe haben damit idR keine
Probleme, können hier aber von bedingter Ausführung profitieren (ggf.
kontrollieren!).
Hihi, ich hätte die zweite Version nicht schreiben sollen. Die ist eher
für Matlab interessant (Multiplikation ist dort billiger als ein
branch).
Die Frage ist: Wie macht man diese häufige Problemstellung im
Embedded-Bereich? Gibt's da vielleicht noch lustige Sachen mit XORs oder
Zweierkomplement, auf die man nicht beim ersten Gedanken kommt?
Walter Tarpan schrieb:> Gibt's da vielleicht noch lustige Sachen mit XORs oder> Zweierkomplement, auf die man nicht beim ersten Gedanken kommt?
Im Einerkomplement wirds einfach. ;-)
Wobei das auch beim Zweierkomplement geht, wenn sign = 0/-1 für +/-:
return (getincrement() ^ sign) - sign;
aber auch hier hängt es vom Einzelfall ab, ob das was bringt.
Astrein sauberes C ist das zudem nicht.
Hallo zusammen,
danke für die zahlreichen Beiträge
Max H. schrieb:> Was macht getincrement(); eigentlich?
Das ist nur ein Platzhalter, um das Problem zu verdeutlichen. Mit dem
folgenden Prototypen: int8_t getincrement(void);
A. K. schrieb:> Einmal mehr: Das ist> eine Einzelfallfrage.
Soetwas habe ich schon befürchtet. Gut, die Einzelfälle sind hier
bekannt: AVR (ATmega644) und ARM Cortex M3 (STM32F103), jeweils mit GCC.
Dieses Problemklasse müßte ja eigentlich total häufig vorkommen. Bei mir
wird einfach eine Drehrichtung eines Motors im EEPROM abgelegt und die
gepollte Routine recht oft in einem Interrupt aufgerufen.
Deswegen interessierte mich, ob es noch andere Lösungsansätze gibt als
- Multiplikation explizit ausführen
- Verzweigung
- Aufgerufene Funktion über Funktionszeiger aufrufen und bei Bedarf
austauschen
Viele Grüße
W.T.
Walter Tarpan schrieb:> Deswegen interessierte mich, ob es noch andere Lösungsansätze gibt als> - Multiplikation explizit ausführen> - Verzweigung> - Aufgerufene Funktion über Funktionszeiger aufrufen und bei Bedarf> austauschen
Ja gibt es. Inline-Code!!! Der Aufwand für Call und Return dürfte
deutlich über dem für die Vorzeichenrechnung liegen. Also ein
include-File:
#define oftgepollteroutine(vz) (vz ? getincrement() : -getincrement())
Du sparst das gesamte Stackhandling ohne Verständnisverlust.
Grüße, Kurt
Wenn der µC einen Befehl zum Negieren einer Variablen hat, könnte es so
gut gehen. Sign ist '0' wenn positiv und '1' wenn negativ.
In PIC24asm könnte das dann so aussehen:
Max H. schrieb:> In PIC24asm könnte das dann so aussehen:
Nur hast du genau wie ich vorhin übersehen, dass hier mindestens 24 Bits
gefragt sind. Das macht die Sache bei 8/16-Bittern etwas komplexer.