mikrocontroller.net

Forum: Compiler & IDEs Präprozessor Abfrage Verknüpfung was läuft falsch?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von MOBA 2. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche eine Verknüpfung im Präprozessor zu machen, klappt 
irgendwie nicht so wirklich
#define SET_SW1(rechts, stop) \
{        \
  if (stop)  \
  {  \
    DIS_SW1;  \
    
    OCR1A = NULL;  \
    OCR2B = NULL;  \
  }  \
  else
  {
    EN_SW1;  \
    
    if (rechts)  \
    {  \
      OCR1A = decoder.system.switch1.dimmvalue;  \
      OCR2B = NULL;  \
    } \
    else  \
    {  \
      OCR1A = NULL;  \
      OCR2B = decoder.system.switch1.dimmvalue;  \
    }  \
  }  \
}

Wenn ich nur normale Ausführungen reinschreibe (bspw DDRB = 0\ DDRC = 3\ 
etcc...) dann geht das.

Eigentlich wollte ich das auch ganz gerne so haben, dass dort keine 
echte if-else sondern wiederum eine #if #else ist, sodass an den 
Programmstellen nur direkt die 2-3 Zeilen Zuweisung der Register 
eingefügt werden, und nicht nochmal mit unterverweigung.

Im Programm steht dann nur sowas wie: SET_SW1(TRUE, FALSE)

: Verschoben durch Moderator
von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Das sind Leezeilen im Code, die beenden das Makro:
#define SET_SW1(rechts, stop) \
{        \
  if (stop)  \
  {  \
    DIS_SW1;  \
    <---- Leerzeile  ohne Backslash
    OCR1A = NULL;  \


Nimm die mal raus.

Marius D. schrieb:
> Eigentlich wollte ich das auch ganz gerne so haben, dass dort keine
> echte if-else sondern wiederum eine #if #else ist,

Kann man machen, dann brauchts aber IMO mehrfaches Parsen. Der Optimizer 
schmeisst aber ein if (0) raus, bzw. den else {} Teil bei if (1).

von Daniel A. (daniel-a)


Bewertung
0 lesenswert
nicht lesenswert
Marius D. schrieb:
> Eigentlich wollte ich das auch ganz gerne so haben, dass dort keine
> echte if-else sondern wiederum eine #if #else ist, sodass an den
> Programmstellen nur direkt die 2-3 Zeilen Zuweisung der Register
> eingefügt werden, und nicht nochmal mit unterverweigung.

Das bringt zwar eher nachteile, müsste aber machbar sein.

Ungetestet:
#define SET_SW1(rechts, stop) \
  SET_SW1_STOP_ ## stop(rechts)

#define SET_SW1_STOP_TRUE(X) \
  { \
    DIS_SW1; \
    OCR1A = NULL; \
    OCR2B = NULL; \
  }

#define SET_SW1_STOP_FALSE(rechts) \
  { \
    EN_SW1; \
    SET_SW1_RECHTS_ ## rechts() \
  }

#define SET_SW1_RECHTS_TRUE() \
  OCR1A = decoder.system.switch1.dimmvalue; \
  OCR2B = NULL;

#define SET_SW1_RECHTS_FALSE() \
  OCR1A = NULL; \
  OCR2B = decoder.system.switch1.dimmvalue;

: Bearbeitet durch User
von A. K. (prx)


Bewertung
1 lesenswert
nicht lesenswert
Inline-Funktionen schreiben sich weniger krampfig.

von PittyJ (Gast)


Bewertung
2 lesenswert
nicht lesenswert
Warum geht nicht eine normale Funktion?
Die ist übersichtlicher, wartbarer, und der Autor muss nicht denken.

von MOBA 2. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
PittyJ schrieb:
> Warum geht nicht eine normale Funktion?
> Die ist übersichtlicher, wartbarer, und der Autor muss nicht denken.

Kostet mir zu viel Zeit + Speicher.

von MOBA 2. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Das bringt zwar eher nachteile, müsste aber machbar sein.


Danke, ich werde es später testen. Warum bringt das Nachteile? Der 
Compiler setzt doch dort einfach die Zeilen hin (wie ein define), das 
sollte doch exakt der gleiche Code sein, als wenn ich an den Stellen das 
dort manuell hinschreibe.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Marius D. schrieb:

> Kostet mir zu viel Zeit + Speicher.

Gemessen oder geraten?

Ansonsten: inline-Funktion.

„Zu viel Zeit + Speicher“ ist ohnehin suspekt: wenn man schnell sein
will, braucht man in der Regel mehr Speicher (inlining, egal ob nun
als inline-Funktion oder durch einen Makro).

Wer solch einen Präprozessor-Spaghetti im 21. Jahrhundert noch baut,
sollte schon 1.) triftige Gründe dafür haben und 2.) in der Lage
sein, ihn auch syntaktisch korrekt niederzuschreiben (siehe Leerzeile).

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> (siehe Leerzeile).

Nicht nur die, das erste "else" ist auch nicht koscher.

von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht so recht.

Also Ich bin ja nun wahrlich selber einer der gelegentlich ner wirklich 
nützlichen Makrokonstruktion nicht abgeneigt ist, meistens dann wenn sie 
einem Arbeit spart meist für Sachen die man in C einfach nicht 
vernünftig hinschreiben kann, aber das Ding da oben halte ich wirklich 
keinesfalls auch nur annähernd für so einen Kandidaten.

Schreib das lieber mal als inline Funktion und beachte wie das dann 
einfacher zu schreiben, zu lesen, zu warten ist, wie es annähernd oder 
gar exakt den selben Code erzeugen wird und wie Du unterm Strich kein 
bisschen Ersparnis oder Erleichterung gehabt hättest mit diesem Makro.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Bewertung
0 lesenswert
nicht lesenswert
Marius D. schrieb:
> Daniel A. schrieb:
>> Das bringt zwar eher nachteile, müsste aber machbar sein.
>
> Danke, ich werde es später testen. Warum bringt das Nachteile? Der
> Compiler setzt doch dort einfach die Zeilen hin (wie ein define), das
> sollte doch exakt der gleiche Code sein, als wenn ich an den Stellen das
> dort manuell hinschreibe.

Ja, schon, aber das Macro setzt voraus, dass TRUE oder FALSE übergeben 
werden, dass TRUE und FALSE nicht durch ein define verändert wurden, und 
kann nicht mit Variablen verwendet werden. Zudem bringt es vermutlich zu 
eingeschalteter -O3 und -ffunc-section kein Platz oder Performance 
Gewinn gegenüger einer gewönlichen funktion, jedenfalls keinen 
Signifikanten.

Ich sliesse mich daher den anderen an, dass hier eine Funktion das beste 
wäre. Da hier TUE und FALSE sowiso nicht variabel sind, könntest du 
eigentlich auch einfach 3 Defines oder 3 Funktionen machen, sollte aber 
keine grossen unterschiede machen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Daniel A. schrieb:
> eingeschalteter -O3

Vorsicht: -O3 optimiert sehr aggressiv auf maximale Geschwindigkeit,
ohne Rücksicht auf die Codegröße.  Da werden dann Schleifen entrollt,
was das Zeug hält etc. pp.

von MOBA 2. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe immer nur -01 als Optimierung.

Habe es jetzt mit inline gemacht, war tatsächlich doch kleiner als das 
Macro von oben, aber im Endeffekt sollte es auch nicht größer sein, von 
daher ist alles gut jetzt.

von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Marius D. schrieb:
> Ich habe immer nur -01 als Optimierung.

Warum?

Einserseits willst Du Zeit und Flash sparen durch krude 
Quelltextverunstaltungen, andererseits verbietest Du dem Compiler die 
meisten Optimierungen.

Ich empfehle normalerweise -Os -flto.

von MOBA 2. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
> Marius D. schrieb:
>> Ich habe immer nur -01 als Optimierung.
>
> Warum?
>
> Einserseits willst Du Zeit und Flash sparen durch krude
> Quelltextverunstaltungen, andererseits verbietest Du dem Compiler die
> meisten Optimierungen.
>
> Ich empfehle normalerweise -Os -flto.

Optimierung auf Teufel komm raus ist bei komplexen Programmen (zumindest 
was ich für Erfahrungen gemacht habe) einfach nur scheiße.

Tlws. macht er dann was völlig anderes als programmiert (lässt bspw. 
Schleifen weg, verkürzt die weil er denkt es wird gesprungen o.ä.) und 
nicht immer ist dadurch der Code wirklich kleiner. Ich habe die 
Erfahrung gemacht (auf komplexere Programme bezogen), ist es mit -O1 am 
kleinsten. Wenn man was größeres nimmt wird's wieder etwas größer. Kommt 
aber stark auf das Programm an. Beim Bootloader hat das was gebracht auf 
maximum, sogar extrem viel. Aber das Programm besteht auch hauptsächlich 
aus mehreren Abfragen und 2 Schleifen. Wenn man viel Strinverarbeitungen 
bspw. hat habe ich nicht so gute Erfahrungen damit gemacht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
Marius D. schrieb:
> Tlws. macht er dann was völlig anderes als programmiert

Dann ist es falsch programmiert.

Außer dem Timing und der Codegröße sollte sich die grundlegende
Funktion des Codes durch die Optimierung nicht ändern.

von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Marius D. schrieb:
> Tlws. macht er dann was völlig anderes als programmiert (lässt bspw.
> Schleifen weg, verkürzt die weil er denkt es wird gesprungen o.ä.)

Das mach doch nichts?! Konstrukte die für die Funktion nicht relevant 
sind und die das Ergebnis nicht beeinflussen kann man weglassen. 
Eingabe und Ausgabe eines Programmfadens bleiben gleich und das ist 
die einzige Garantie die ein C-Compiler überhaupt geben kann und soll. 
Mehr soll er nicht. Und das ist auch das einzige worauf es ankommt. Und 
wie der Compiler das macht bleibt ihm überlassen.

Wenn Du Unterschiede in den Ausgaben des Programms bemerkst hast Du 
vermutlich vergessen alle Eingaben und Ausgaben als solche zu 
deklarieren oder Du hast anderweitig grob geschlampt (undefiniertes 
Verhalten, nicht initialisierte Variablen, etc.) und wenn Du dann ohne 
Optimierung trotzdem richtige Ergebnisse bekommst ist das nur das 
Ergebnis einer Verkettung bemerkenswerter Zufälle.

Wenn Dein Programm bei anderen Optimierungseinstellungen oder mit einem 
anderen Compiler nicht mehr funktioniert dann ist das der Tatsache 
geschuldet daß es aufgrund seiner Fehlerhaftigkeit eigentlich überhaupt 
nie hätte funktionieren müssen.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Marius D. schrieb:
> Optimierung auf Teufel komm raus ist bei komplexen Programmen (zumindest
> was ich für Erfahrungen gemacht habe) einfach nur scheiße.

Meine Erfahrung ist, dass das in der Regel nicht an der Komplexität, 
sondern an Fehlern im Programm oder fehlerhaften Annahmen durch den 
Programmierer liegt, was ich auch hier vermute:

> Tlws. macht er dann was völlig anderes als programmiert (lässt bspw.
> Schleifen weg, verkürzt die weil er denkt es wird gesprungen o.ä.)

Viele sind sich der as-if-Regel nicht bewusst, die aber eigentlich in 
diesem Zusammenhang essenziell ist. Die besagt, dass der Compiler den 
Code beliebig verändern darf, solange das "observable behaviour", also 
das beobachtbare Verhalten gleich bleibt. Und das ist definiert als 
File-Zugriffe und Zugriffe auf volatile-Variablen. Alles andere darf der 
Compiler beliebig verändern - auch das Timing, solange nur die oben 
besagten Zugriffe alle noch da sind und in der richtigen Reihenfolge 
durchgeführt werden.
Von dieser Regel macht vor allem der Optimizer regen gebrauch. Sein Ziel 
ist, den Code so schnell und/oder klein wie möglich zu machen, ohne dass 
sich das beobachtbare Verhalten ändert. Alles, was dafür nicht benötigt 
wird, schmeißt er deshalb raus.
Ein typischer Fehler, der daraus resultiert, sind zum Beispiel 
"Warteschleifen", wo eine leere for-Schleife geschrieben wird und der 
Programmierer sich wundert, warum der Compiler die verwirft. Nun, da sie 
keinen Effekt hat außer Platz und Zeit zu verbrauchen, schmeißt der 
Optimizer sie raus, denn der ist ja gerade dazu da, den Platz- bzw. 
Zeitverbrauch zu minimieren.

: Bearbeitet durch User

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.