Ich habe eine dämliche Frage, für die ich mich ja eigentlich schämen
muß, aber ich komme so auf die Schnelle nicht drauf ( smile ich freue
mich auf die negativen Lesenswert Bewertungen, aber auch auf die,
möglicherweise, Lösung, die dann 1000 negative Bewertungen wert ist)
Unter avr-gcc und arm-none-eabi-gcc funktioniert in meinen Sourcen
folgendes (alte Codes von mir halt):
1
if (bl & 0x01) charlieA_set(); else charlieA_clr();
Unter riscv-none-elf-gcc (Version 14.2.0) funktioniert das nicht und ich
muß das hier (mit geschweiften Klammern schreiben.
Gibt es einen Compilerschalter mit dem das so funktioniert wie im ersten
Beispiel (augenscheinlich verwende ich für's Compileren die gleichen
Standartoptionen) ?
Ralph S. schrieb:> Unter riscv-none-elf-gcc (Version 14.2.0) funktioniert das nicht
Was heißt "funktioniert nicht"?
Bekommst Du eine Fehlermeldung, oder macht der compilierte Code etwas
anderes als Du erwartest?
Am gezeigten Code-Fragment ist micht falsch, und auch nichts, was eine
bestimmte Compiler-Version oder -Option erfordert.
Zeige mehr vom Quelltext und die Fehlermeldung.
Ralph S. schrieb:> Gibt es einen Compilerschalter mit dem das so> funktioniert wie im ersten Beispiel
Du buddelst auf der falschen Baustelle.
> Ist charlieA_set ein Makro?
Eigentlich sollte man Makros mit Großbuchstaben benennen, damit sowas
nicht passiert, bzw. auffällig ist.
Arduino F. schrieb:> Eigentlich sollte man Makros mit Großbuchstaben benennen, damit sowas> nicht passiert, bzw. auffällig ist.
Wenn er es in Großbuchstaben schreibt, behebt er damit nicht das
Problem. Es hat hier gerade keinen Sinn, über Konventionen zu
diskutieren.
Meine Vermutung ist auch, dass es sich um ein schlecht gekapseltes Makro
handelt, was aus zwei oder mehr Statements besteht. Damit passt dann
ohne Klammern der else-Zweig nicht mehr.
Abhilfe:
Die Macros in
1
do{....}while(0)
einbetten.
Oder grundsätzlich geschweifte Klammern nach if, while, for verwenden,
was ich persönlich immer mache. Der Source wird lesbarer und eine
nachträgliche Einfügung eines zusätzlichen Statements in den if- oder
else-Zweig führt nicht mehr zu einer nachträglichen zwangsweisen
Einfügung von geschweiften Klammern, denn diese sind ja schon da!
Frank M. schrieb:> Meine Vermutung ist auch, dass es sich um ein schlecht gekapseltes Makro> handelt,
Das würde allerdings, auch bei einem anderen C/C++ Compiler, genau so
ins Essen brechen.
Oder?
Mir fällt es schwer, da die Ursache zu sehen.
Arduino F. schrieb:> Das würde allerdings, auch bei einem anderen C/C++ Compiler, genau so> ins Essen brechen.
Wenn das Macro für eine andere Plattform (arm-none vs. riscv-none)
anders aussieht, dann nicht unbedingt.
Nun ja....
Da können wir uns ja glücklich schätzen, dass das exakte Fehlerbild und
auch das vermeidliche Makro geheim bleiben müssen. So kann man, völlig
ungestört durch Fakten, herrlich im Nebel stochern.
Nemopuk schrieb:> Zeige mehr vom Quelltext und die Fehlermeldung.
Ich provoziere das Verhalten einmal mit dem folgenden Code. Aus den
obigen Antworten geht hervor, dass das Verhalten in der if-else
Bedingung tatsächlich darauf zurück zu führen ist, dass die Anweisungen
Makros sind.
1
#define led_init() PC0_output_init()
2
#define led_set() PC0_set()
3
#define led_clr() PC0_clr()
4
5
void dummyout(int val)
6
{
7
}
8
9
int main()
10
{
11
volatile int a,c;
12
SystemInit();
13
led_init();
14
c= 0;
15
while(1)
16
{
17
if ((c % 9) == 0) dummyout(4); else dummyout(9);
18
if ((c % 13) == 0) led_set(); else led_clr();
19
dummyout(a);
20
}
21
}
Harald K. schrieb:> Bekommst Du eine Fehlermeldung, oder macht der compilierte Code etwas> anderes als Du erwartest?
Die "dummyout" Anweisungen werden klaglos übersetzt, die "led_set"
Anweisungen produzieren diesen Fehler:
1
scratch.c: In function 'main':
2
scratch.c:54:35: error: 'else' without a previous 'if'
Frank M. schrieb:> Wenn er es in Großbuchstaben schreibt, behebt er damit nicht das> Problem. Es hat hier gerade keinen Sinn, über Konventionen zu> diskutieren.
:-) Danke .... Ich weiß, dass es eine allgemeine Konvention ist, Makros
groß zu schreiben, aber für einige Fälle im Programm gefällt mir das bis
heute nicht.
>> Meine Vermutung ist auch, dass es sich um ein schlecht gekapseltes Makro> handelt, was aus zwei oder mehr Statements besteht. Damit passt dann> ohne Klammern der else-Zweig nicht mehr.
Ganz genau das ist es (wie ich das jetzt herausfinde).
Frank M. schrieb:> Oder grundsätzlich geschweifte Klammern nach if, while, for verwenden,> was ich persönlich immer mache.
Mittlerweile mache ich das auch, dieses Verhalten habe ich immer dann,
wenn ich alten Code (eben "Jugendsünden" von mir) portiere und
wiederverwende.
Die if-else Bedingung wird korrekt übersetzt, wenn man bspw. das Makro
ähnlich dem hier kapselt:
1
#define led_set() ({PC0_set();})
Scheinbar sind die Makros der GPIO-Portzugriffe wie bspw. PC0_set(),
die ich für avr-gcc und arm-none-eabi-gcc geschrieben habe besser
gekappselt, als die, die für riscv-none-elf-gcc (und innerhalb dieser
weitere Makros verwendet werden, die nicht von mir sind).
Abschließend vielen Dank für Euro Antworten (und ein schönes Wochenende
für Euch)
Tue dir einen Gefallen und vermeide künftig die Verwendung von Makros
anstelle von Funktionen. Das provoziert nur Probleme und schwer
verständliche Fehlermeldungen.
Solche einzeiligen Funktionen optimiert der gcc schon weg. Darum musst
du dich nicht manuell kümmern.
Ralph S. schrieb:> #define led_init() PC0_output_init()> #define led_set() PC0_set()> #define led_clr() PC0_clr()
Wenn Du wirklich herausfinden willst, was da passiert, sieh Dir an, wie
PC0_set definiert ist. Das wird wenigstens bei einem Deiner beiden
Compiler wieder ein Macro sein.
Zum Thema Macros anstelle von Funktionsaufrufen hat Nepomuk schon fast
alles wesentliche geschrieben.
Wenn Du tatsächlich glaubst, an so einer Stelle bereits optimieren zu
müssen, denke a) an "premature optimisation is the root of all evil" und
b) daran, daß Du auch komplette Funktionen via inline deklarieren
kannst. Und denke nochmal an a).
Ralph S. schrieb:> Ich weiß, dass es eine allgemeine Konvention ist, Makros> groß zu schreiben, aber für einige Fälle im Programm gefällt mir das bis> heute nicht.
Das ist ja das schöne an C: man kann sich damit nicht nur selber ins
Knie schiessen, man hat sogar die freie Wahl des Kalibers, und auch, wie
oft es vorher noch durch die Brust und Auge gehen soll.
Oliver
Oliver S. schrieb:> Das ist ja das schöne an C: man kann sich damit nicht nur selber ins> Knie schiessen, man hat sogar die freie Wahl des Kalibers, und auch, wie> oft es vorher noch durch die Brust und Auge gehen soll.
Man sollte schon wissen, was man tut.
Nemopuk schrieb:> Tue dir einen Gefallen und vermeide künftig die Verwendung von Makros> anstelle von Funktionen. Das provoziert nur Probleme und schwer> verständliche Fehlermeldungen.
Diese Ansicht teile ich nicht. Denn gerade dafür sind Makros ja gemacht.
Und bewaffnet mit der Fehlermeldung kann man dem Compiler ja den
präprozessierten Quelltext entlocken (gcc -E) und sieht das Problem dann
meist sofort.
> Solche einzeiligen Funktionen optimiert der gcc schon weg. Darum musst> du dich nicht manuell kümmern.
Jein. Die Optimierung ist nicht das vordringliche Problem. Obwohl es
natürlich lästig ist, wenn der Compiler für eine einzige Instruktion
einen Funktionsaufruf mit Prolog und Epilog konstruiert. Und der
Compiler optimiert es ja auch nicht immer und automatisch weg. Und
ältere Compiler können es u.U. gar nicht. Das sind mir zuviele Wenns.
Ich gestalte meine µC-Programme meist so, daß ich Hardware-Zugriffe
(insbesondere Port-Zugriffe) kapsele. Also ein einfaches HAL das in
hal.h kommt und überall includiert wird wo ich es brauche. Und da sind
es der Einfachheit halber eben Makros, die wie Funktionen aussehen.
Natürlich könnte ich das in Deklaration und Definition trennen, aber
wozu? Das brigt (mir) keinen Mehrwert. Und was irgendwer als "reine
Lehre" propagiert, geht mir am A**** vorbei. Zumal die "reine Lehre" oft
nur die "aktuelle Mode" ist. Ich bin zu alt um der Mode hinterher zu
laufen.
Axel S. schrieb:> Denn gerade dafür sind Makros ja gemacht.
Für Funktionen sind Funktionen gemacht worden.
Axel S. schrieb:> Und ältere Compiler können es u.U. gar nicht.
Das "Problem" haben wir seit mehr als 15 Jahren nicht mehr. Halte dich
doch nicht unnötig mit Einschränkungen auf, die schon lange überwunden
sind!
Axel S. schrieb: Und was irgendwer als "reine
> Lehre" propagiert, geht mir am A**** vorbei. Zumal die "reine Lehre" oft> nur die "aktuelle Mode" ist. Ich bin zu alt um der Mode hinterher zu> laufen.
Das eingangs Problem, ist das Produkt aus mehreren Verstößen gegen die
abgelehnten modernen Methoden. Diese "modernen" Empfehlungen für Makros
sind sicher schon 1/2 Jahrhundert alt
Die Verstöße:
1. Kleinschreibung des Makro Bezeichners
2. Vortäuschung einer Funktion durch die völlig unnützen ()
Das ist eine der klassischen Methoden, wie man sich selber und andere
verarschen kann.
Einzig und alleine weil die Verarschung hübscher aussieht, als die
Realität.
Klarer: Eine Dummheit.
> Und da sind es der Einfachheit halber eben Makros,> die wie Funktionen aussehen.
Wenn es wie ein Funktionsaufruf aussieht, sollte es sich auch wie eine
Funktion verhalten. Das entspricht dem "Prinzip der geringsten
Verwunderung".
Der TO ist in die selbst gestellte Falle getappt.
Und deine Argumentation sagt mir, dass du auch mit einem Fuß darin
stehst.
Das nur weil die Falle schöner aussieht, als die Wahrheit.
Ralph S. schrieb:> Ich habe eine dämliche Frage, für die ich mich ja eigentlich schämen> muß
Ja, beides stimmt. Stell Dich also sofort in die Ecke.
Bloß nicht das Target benennen und auf keinen Fall die erste
Fehlermeldung C&P (d.h. im exakten Wortlaut).
Wer antworten will, soll es ja schön schwer haben.
Nur echte Weicheier posten eine Codefrage so vollständig, daß man sie
dem Compiler vorsetzen kann.
Für die AVRs benutze ich meine "sbit.h", die alle IO-Pins einfach als
Bitvariable definiert. Bitvariablen kann man nämlich direkt zuweisen
oder testen ohne umständliches if/else Gemäre.
Ralph S. schrieb:> die gleichen> Standartoptionen
Nochmal in die Ecke stell, es gibt keine Art des Stehens.
Peter D. schrieb:> Stell Dich also sofort in die Ecke.
Wenn jemand einen Fehler nicht selber finden kann ist es völlig normal
dass er nicht weiß, welcher Kontext notwendig ist, für eine
erfolgversprechende Fehlersuche.
Es ist völlig unangemessen sich sein eigens Ego auf Kosten Unterlegener
polieren zu wollen. Eine einfache Frage/Hinweis nach mehr Kontext ist
völlig ausreichend.
> Nochmal in die Ecke stell, es gibt keine Art des Stehens.
Wenn man schon das Bedürfnis hat Rechtschreibfehler zu korrigieren, kann
man auch darauf hinweisen dass "Standard" mit "d" am Ende geschrieben
wird und das ein häufiger Fehler ist.
Auch hier ist es völlig unnötig, sich auf Kosten andere zu erbauen ohne
einen einzigen Hinweis auf den Rechtschreibfehler.
Arduino F. schrieb:> Die Verstöße:> 1. Kleinschreibung des Makro Bezeichners> 2. Vortäuschung einer Funktion durch die völlig unnützen ()
Wenn sich ein Makro in jeder Hinsicht (also sowohl syntaktisch als auch
semantisch) wie eine gewöhnliche C/C++-Funktion verhält, ist es IMHO
völlig in Ordnung, es wie eine solche zu behandeln.
Ein Makro verhält sich wie eine gewöhnliche Funktion, wenn folgende
Bedingungen erfüllt sind:
1. Es hat wie eine gewöhnliche Funktion eine in Klammern eingeschlossene
Argumentliste. Hat das Makro keine Argumente, bleibt der Raum
zwischen den Klammern leer.
2. Der Makroaufruf kann überall dort stehen, wo auch ein Funktionsaufruf
stehen kann, also insbesondere auch innerhalb einer if-Anweisung.
3. Die Makroargumente werden genau ein einziges Mal ausgewertet, wie
dies auch bei einem Funktionsaufruf der Fall ist.
Bei solchen Makros können und sollten IMHO dieselben Namenskonventionen
(Groß-/Kleinschreibung, Verwendung von Underscores usw.) wie für
gewöhnliche Funktionen zur Anwendung kommen. Guter Stil ist es zudem,
wenn nebeneffektbehaftete Makros ein Verb im Namen enthalten.
Um Bedingung 2 zu erfüllen, müssen bei Makros, die mehrere Anweisungen
enthalten, diese in do { ... } while(0) eingeschlossen werden.
Alternativ kann auch ({ ... }) verwendet werden (Statement Expression),
was aber nicht standardkonform ist. Statement Expressions sind auch
manchmal notwendig, um Bedingung 3 zu erfüllen.
Bei den Makros des TE ist Bedingung 2 nicht erfüllt, weil offensichtlich
irgendwo weiter unten in der Makrohierarchie ein Makro mit mehreren
Anweisungen ohne die vorgenannten Maßnahmen definiert wurde.
Arduino F. schrieb:> Das ist eine der klassischen Methoden, wie man sich selber und andere> verarschen kann.> Einzig und alleine weil die Verarschung hübscher aussieht, als die> Realität.>> Klarer: Eine Dummheit.>> ...>> Wenn es wie ein Funktionsaufruf aussieht, sollte es sich auch wie eine> Funktion verhalten. Das entspricht dem "Prinzip der geringsten> Verwunderung".
Verarschung, Dummheit, ...
Starke Worte von einem, der sich Arduino-Fanboy nennt :)
Gerade die Arduino-Umgebung macht vor, wie man es nicht machen sollte.
Mindestens die Makros min, max, abs, constrain und sq erfüllen Bedingung
3 nicht und verhalten sich damit nicht wie gewöhnliche Funktionen.
Trotzdem werden deren Namen entgegen des Fanboys Forderung nicht in
Großbuchstaben geschrieben, und die Doku nennt diese Makros sogar
"function". Immerhin enthält die Doku inzwischen vage Hinweise darauf,
dass diese "Funktionen" gerne mal fehlerhafte Ergebnisse liefern. Besser
als diese Hinweise zu schreiben, wäre es wohl gewesen, das Problem
einfach zu fixen. C++ und der GCC bieten mehr als genug Möglichkeiten
dafür.
Michael schrieb:> Wenn jemand einen Fehler nicht selber finden kann ist es völlig normal> dass er nicht weiß, welcher Kontext notwendig ist, für eine> erfolgversprechende Fehlersuche.
Nö, es ist nicht normal, eine Frage so zu stellen, als käme es auf jede
Sekunde Deiner Schreibarbeit an. Soll sich gefälligst der Helfer mehr
Mühe geben.
Völlig normal ist es aber, sich ein paar Gedanken zu machen, was
notwendig wäre, falls jemand nicht in Deinen Kopf schauen kann.
Die exakte Fehlermeldung ist das absolut mindeste.
Michael schrieb:> ohne> einen einzigen Hinweis auf den Rechtschreibfehler.
Der Hinweis ist doch deutlich genug. Und falls man darüber erst
nachdenken muß, prägt es sich umso besser ein. Man könnte aber auch
einfach aufhören, die rote Wellenlinie unter dem fehlerhaften Wort zu
ignorieren.
> Mindestens die Makros min, max, abs, constrain> und sq erfüllen Bedingung 3 nicht und verhalten> sich damit nicht wie gewöhnliche Funktionen.
Welche davon ist auf meinem Mist gewachsen?
Keine!
Dein Versuch mich dafür verantwortlich zu machen ist gründlich daneben.
Eines Moderators nicht würdig!
> Starke Worte von einem, der sich Arduino-Fanboy nennt :)
Ja, von mir aus...
Ich verstehe sogar den Wunsch, mich auf diese Art und weise
diskriminieren/verletzen zu wollen.
Ist es doch mit eine der typischen Arduino Basher Methoden.
Noch weit unter den Niveau einer Bordsteinkante.
Von mir aus könnt ihr euch weiter gerne mit solchen Fake Funktionen
rumschlagen...
Wie dumm das laufen kann sehen wir im Eingangsposting.
Oder eben auch wenn eine der drei genannten Fake Funktionen mit z.B. i++
aufgerufen wird.
Arduino F. schrieb:>> Mindestens die Makros min, max, abs, constrain>> und sq erfüllen Bedingung 3 nicht und verhalten>> sich damit nicht wie gewöhnliche Funktionen.>> Welche davon ist auf meinem Mist gewachsen?> Keine!
Das habe ich auch nicht behauptet. Ich weiß, dass du zwar ein Fan von
Arduino bist, aber nicht zu dessen Entwicklergruppe gehörst.
Arduino F. schrieb:> Ich verstehe sogar den Wunsch, mich auf diese Art und weise> diskriminieren/verletzen zu wollen.
Ich will dich damit nicht diskriminieren oder verletzen, sondern war
nur etwas erstaunt darüber, dass ausgerechnet ein Arduino-Fanboy die
Arduino-Macher der Verarsche und der Dummheit bezichtigt. Ich finde es
zwar genauso wie du nicht gut, was die Jungs da fabriziert haben, aber
ich würde sie deswegen nicht mit solchen Worten beschimpfen oder gar
beleidigen.
Es bleibt allerdings die Frage, warum man Dinge in Macros verpackt, die
so tun, als ob sie eine Funktion wären.
Das ist premature optimisation, denn das, was man damit wohl erzielen
will (kein Funktionsaufruf, kein Overhead deswegen) kann der Compiler
auch selbst - "inline" ist das magische Wort dafür.
> aber ich würde sie deswegen nicht mit solchen Worten beschimpfen> oder gar beleidigen.
Punkt 1:
Ich habe nicht angefangen über die Arduino Infrastruktur zu schimpfen,
Das hast du gemacht und mir gerade in den Mund gelegt.
Punkt 2:
Der TO hast sich mit seinen Makros selber verarscht und dann das if bzw.
den Compiler und seine Schalter verantwortlich gemacht.
Und ja ich halte es für dumm, Funktionen mit Makros vorzutäuschen.
Egal wer das tut.
Punkt 3:
Es macht einen Unterschied, ob ich ein Verhalten oder eine Person für
Dumm erkläre.
Denn, ein Verhalten kann sich ändern. Eine dumme Person kann das nicht.
Also nein, ich habe keine Person als dumm bezeichnet.
Und damit auch niemanden beleidigt.
Merke:
Selbst die schlauesten Leute können dumme Ideen haben.
Peter D. schrieb:> Ralph S. schrieb:>> die gleichen>> Standartoptionen>> Nochmal in die Ecke stell, es gibt keine Art des Stehens.
Mein passiv gekühlter PC hat genau eine Standart-Option: hochkant.
Seitlich ist extra ein großer gelber Pfeil aufgedruckt.
Die andere Lehre aus diesem Thread: wenn man etwas als Funktion
formulieren kann, baut man gefälligst kein Macro! Was spricht denn
dagegen? Jedenfalls, wenn man mit arm-none-eabi-gcc oder
riscv-none-elf-gcc unterwegs ist?
Harald K. schrieb:> Das ist premature optimisation, denn das, was man damit wohl erzielen> will (kein Funktionsaufruf, kein Overhead deswegen) kann der Compiler> auch selbst - "inline" ist das magische Wort dafür.
Das "inline"-Schlüsselwort ist nur ein Vorschlag an den Compiler. Was
dieser damit macht, ist seine Sache und hängt u.a. vom Compilertyp, der
Version und der ausgewählten Optimierungsstufe ab. Wenn man das "inline"
weglässt, kann der Compiler einen Funktionsaufruf dennoch inlinen, wenn
er es für sinnvoll hält. Der GCC tut dies bei kleinen Funktionen und
eingeschalteter Optimierung auch recht häufig, so dass die Verwendung
von "inline" oft gar keinen Unterschied macht.
Um dem Programmierer etwas mehr Kontrolle zu geben, bieten die meisten
Compiler die Möglichkeit, Inlining zu erzwingen (bspw. GCC und Clang mit
__attribute__((always_inline))), aber dies ist nicht für alle Compiler
einheitlich und schon gar nicht vom C-Standard abgedeckt.
Garantiertes, standardkonformes und portables Inlining ist deswegen nur
mit Makros möglich.
Da Mikrocontrollerprogramme in der Regel ohnehin nur eingeschränkt
portabel sind, verwende ich dort gerne Inline-Funktionen statt
function-like Makros, dann aber oft mit dem always_inline-Attribut, um
nichts dem Zufall zu überlassen.
Yalu X. schrieb:> Das "inline"-Schlüsselwort ist nur ein Vorschlag an den Compiler.
Gewiss, aber die Fälle, wo man sich als Programmierer ernsthaft Gedanken
darüber machen muss, die Fälle, wo der Overhead normale Funktionsaufrufe
tatsächlich ein Problem darstellt, sind verschwindend gering.
Das ist genauso wie das von manchen Leuten betriebene krampfhafte
Vermeiden von Floating-Point-Arithmetik oder der Verwendung von
printf.
Die Leute haben irgendwann irgendwo mal aufgeschnappt, daß das Probleme
bereiten kann, viel Speicher verbrauchen kann, und deswegen meiden sie
es wie der Teufel das Weihwasser, völlig egal, ob ihr µC nicht doch zig
Kilobyte brachliegendes Flashrom hat, und auch völlig egal, ob ihr µC
nicht Größenordnungen schneller ist als der, für den das mal als Problem
beschrieben wurde.
Und das ist es, was ich premature optimisation nenne. Unnötiger
fehlerträchtiger Aufriss, um ein nicht existierendes Problem zu umgehen.
Ein Makro garantiert auch nicht dass der Code ge-inlined wird.
Insbesondere mit der bei AVR beliebten Optimizer Stufe -s zerlegt der
Compiler Funktionen mit wiederholten Zeilen (auch Makros) oft in
Unterfunktionen.
Wer Board-spezifische I/O Zugriffe unbedingt in einer *.h Datei sammeln
will, darf das gerne tun. Das geht mit ganzen Funktionen ebenso, wie mit
Makros.
Harald K. schrieb:> Und das ist es, was ich premature optimisation nenne.
Premature optimisation ist nicht per se schlecht.
Ja, sie ist es, wenn sie ohne Nachzudenken durchgeführt wird.
Sie ist es nicht bei der Entwicklung von HALs, Bibliotheken und
sonstigen für die häufige Wiederverwendung vorgesehenen Softwaremodulen,
da in diesen Fällen damit gerechnet werden muss, dass der Code auch in
zeitkritischen Anwendungen zum Einsatz kommt.
Sie ist es auch nicht, wenn vor vornherein feststeht, dass CPU-Zeit und
Speicher knapp werden, weil bspw. von extern vorgegebene Randbedingungen
keine überdimensionierte Hardware erlauben.
All diejenigen, die auf premature optimisation verzichten, kommen evtl.
irgendwann in eine Situation, in der eine "postmature" optimisation
erforderlich ist.
Was ich damit sagen möchte: Auch wenn Compiler immer besser optimieren,
sollte man die Handoptimierung nicht grundsätzlich verdammen. Natürlich
sollte sie mit Sinn und Verstand durchgeführt werden. Gerade bei so
einfachen Dingen wie das Schalten von Output-Pins beträgt der Overhead
eines Funktionsaufrufs oft ein Vielfaches der eigentlichen Operation,
dabei ist der Aufwand für die Optimierung per Makro oder always_inline
minimal.
> Unnötiger fehlerträchtiger Aufriss, um ein nicht existierendes Problem> zu umgehen.
Im konkreten Fall wurde der Fehler direkt durch den Compiler aufgedeckt.
Das Problem war lediglich, dass der (wohl noch etwas unerfahrene) TE die
Fehlermeldung nicht richtig einordnen konnte. Andere hingegen (Udo K.
und Frank M.) gaben – obwohl sie die Fehlermeldung nicht einmal kannten
– sofort den richtigen Hinweis auf die Fehlerursache, und Frank lieferte
sogar gleich die Lösung mit.
Beim nächsten Mal wird auch der TE nicht mehr lange suchen müssen.
Nemopuk schrieb:> Ein Makro garantiert auch nicht dass der Code ge-inlined wird.> Insbesondere mit der bei AVR beliebten Optimizer Stufe -s zerlegt der> Compiler Funktionen mit wiederholten Zeilen (auch Makros) oft in> Unterfunktionen.
Wirklich? Auch bei so einfachen Dingen wie dem Beschreiben von
I/O-Registern? Das hatte ich noch nie erlebt (zumindest ist es mit noch
nie aufgefallen. Aber das kann natürlich sein und ist auch völlig
richtig, denn mit der Option -Os dagt der Programmier dem Compiler:
"Mach den Code so klein wie möglich, und sei es auf Kosten der
Geschwindigkeit"
Wenn die Geschwindigkeit Priorität hat, wird er die Option -O2 oder -O3
wählen.
Harald K. schrieb:> Unnötiger fehlerträchtiger Aufriss, um ein nicht existierendes Problem> zu umgehen.
Manche Programmiere fühlen sich überlegen, weil sie die Tricks der 80er
Jahre immer noch beherrschen. Ich kann das gut nachempfinden. Aus dem
Grund hatte ich lange Zeit das Arduino System abgelehnt. Mir ist das
erst im Nachhinein bewusst geworden.
Yalu X. schrieb:> Gerade bei so> einfachen Dingen wie das Schalten von Output-Pins beträgt der Overhead> eines Funktionsaufrufs oft ein Vielfaches der eigentlichen Operation
Aber gerade diese Funktionsaufrufe optimiert der Compiler bereits weg.
Yalu X. schrieb:> Wirklich? Auch bei so einfachen Dingen wie dem Beschreiben von I/O-Registern?
Ein simples SBI oder CBI wird der Compiler nicht zerlegen, sondern
umgekehrt den eventuell überflüssigen Funktionsrahmen drumherum
entfernen (falls vorhanden). Er tut das auch oft bei geringfügig
komplexeren Funktionen, die nur wenige Assembler Befehle ergeben.
Bei der Diskussion sollte man im Hinterkopf behalten, das
Funktionsaufrufe beim AVR "billiger" sind, als z.B bei ARM Cortex-M
basierten Mikrocontrollern.
Nemopuk schrieb:> Insbesondere mit der bei AVR beliebten Optimizer Stufe -s zerlegt der> Compiler Funktionen mit wiederholten Zeilen (auch Makros) oft in> Unterfunktionen.
Nein, soweit ich weiß gibt es eine solche Optimierung (Code Outlining)
nicht im GCC; egal für welche Sprache, egal für welches Target.
Oder kannst du ein Beispiel nennen?
Yalu X. schrieb:> Wirklich? Auch bei so einfachen Dingen wie dem Beschreiben von> I/O-Registern? Das hatte ich noch nie erlebt (zumindest ist es mit noch> nie aufgefallen. Aber das kann natürlich sein und ist auch völlig> richtig, denn mit der Option -Os dagt der Programmier dem Compiler:> "Mach den Code so klein wie möglich, und sei es auf Kosten der> Geschwindigkeit"
Das wäre -Oz. Aber selbst mit -Oz kann / macht GCC kein Code-Outlining.