Forum: Mikrocontroller und Digitale Elektronik Compileroptionen


von Ralph S. (jjflash)


Lesenswert?

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.
1
    if (bl & 0x01) { charlieA_set(); } else { charlieA_clr(); }

Gibt es einen Compilerschalter mit dem das so funktioniert wie im ersten 
Beispiel (augenscheinlich verwende ich für's Compileren die gleichen 
Standartoptionen) ?

von Harald K. (kirnbichler)


Lesenswert?

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?

von Udo K. (udok)


Lesenswert?

Ist charlieA_set ein Makro?

von Nemopuk (nemopuk)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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!

: Bearbeitet durch Moderator
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

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'
3
   54 |     if ((c % 13) == 0) led_set(); else led_clr();
4
      |                                   ^~~~

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)

von Nemopuk (nemopuk)


Lesenswert?

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.

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

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).

von Oliver S. (oliverso)


Lesenswert?

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

von Rahul D. (rahul)


Lesenswert?

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.

von Axel S. (a-za-z0-9)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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!

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

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.

von Michael (Gast)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

> 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.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Harald K. (kirnbichler)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

> 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.

von Bauform B. (bauformb)


Lesenswert?

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?

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Harald K. (kirnbichler)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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.

von Nemopuk (nemopuk)


Lesenswert?

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.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

Harald K. schrieb:
> 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.

Na ja, PC0_set ist ein Makro von mir, aaaaaber dieses ruft seinerseits 
wieder ein Makro aus CH32FUN auf, von dem ich dachte, dass es eine 
Funktion und nicht selbst ein Makro ist (Fehler by me).

Das wird sich erledigen, wenn ich mein Setup durch eigene 
GPIO-Funktionen von CH32FUN ersetzt habe, bis dahin habe ich das in 
PC0_set und Konsorten gekappsel.

Harald K. schrieb:
> 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).

Das hat bei mir mit Optimierung noch nichts zu tun, sondern ist dem 
Grund geschuldet, dass ich für die von mir verwendeten 
Controllerfamilien immer eine Include-Datei habe, bei der ich im Stile 
von PC0_set etc. GPIO's nach demselben Muster anspreche.

Grundsätzlich ist die Anfrage hier einem Irrtum meinerseits geschuldet, 
ich dachte, dass der Compiler die Fehlermeldung:
1
scratch.c: In function 'main':
2
scratch.c:54:35: error: 'else' without a previous 'if'
3
   54 |     if ((c % 13) == 0) led_set(); else led_clr();
4
      |                                   ^~~~

auch bei Funktionsaufrufen auswirft (was der Compiler natürlich nicht 
getan hat), aber wie gesagt hätte ich geschworen (Meineid ?) dass dem so 
ist.

Peter D. schrieb:
> Ja, beides stimmt. Stell Dich also sofort in die Ecke.

ich sehe das jetzt einmal sportlich und mit einem Augenzwinkern: Ich 
stand schon in der Ecke :-)

Peter D. schrieb:
> Ralph S. schrieb:
>> die gleichen
>> Standartoptionen
>
> Nochmal in die Ecke stell, es gibt keine Art des Stehens.

Vielleicht meinte ich ein Kofferwort für "Kunst des Stehens" ? Nein, für 
ein falsch geschriebenes Wort stelle ich mich nicht in die Ecke, denn 
das hier ist ein Technikforum und kein Forum für Deutschlehrer, aber, 
weil es manche Lehrer so mögen:
1
for (int i= 0; i< 100; i++)
2
{
3
  printf("\n\rIch schreibe nie wieder Standard mit 't'");
4
}

Arduino F. schrieb:
> Merke:
> Selbst die schlauesten Leute können dumme Ideen haben.

Ich gehöre zwar nicht zu den schlauesten Leuten, aber dumme Ideen habe 
ich trotzdem.

Yalu X. schrieb:
> 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.

:-) :-) hätte ich richtig hingesehen, hätte ich das wohl auch richtig 
einordnen können. Umso erstaunlicher ist, dass Udo und Frank (ohne die 
Fehlermeldung zu kennen) das korrekt eingeordnet haben: Respekt.

Hier jedoch eine "Frage" (mit Anmerkung): Ich kann mich garantiert nicht 
mit Yalu, Jörg oder Frank messen, aber ab wann gilt man nicht mehr als 
unerfahren? (Ich programmiere seit fast 40 Jahren auch mit C, muß ich 
mich jetzt noch einmal schämen und noch einmal in die Ecke stellen?)

Ich sollte mich an einen meiner Leitsprüche halten: Wer lesen kann, ist 
klar im Vorteil (hier dann Fehlermeldungen).

:-) :) auch wenn ich mich vor Peinlichkeit in die Ecke stellen mußte ein 
herzliches Danke an die, die geholfen haben (bis zur nächsten 
Peinlichkeit),

Ralph

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Ralph S. schrieb:
> Das hat bei mir mit Optimierung noch nichts zu tun, sondern ist dem
> Grund geschuldet, dass ich für die von mir verwendeten
> Controllerfamilien immer eine Include-Datei habe, bei der ich im Stile
> von PC0_set etc. GPIO's nach demselben Muster anspreche.

Ich bin in den moderneren C Eigenheiten nicht ganz so fit wie in C++...
In C++ ist es mittlerweile so, dass man Code in *.h Dateien unterbringen 
kann. Ohne define.
In dem man Funktionen als static oder inline deklariert.
Kann C das mittlerweile auch?

: Bearbeitet durch User
von Udo K. (udok)


Lesenswert?

Ralph S. schrieb:
> Hier jedoch eine "Frage" (mit Anmerkung): Ich kann mich garantiert nicht
> mit Yalu, Jörg oder Frank messen, aber ab wann gilt man nicht mehr als
> unerfahren? (Ich programmiere seit fast 40 Jahren auch mit C, muß ich
> mich jetzt noch einmal schämen und noch einmal in die Ecke stellen?)

Als erfahren gilt man, wenn man in if Ausdrücken Konstanten nicht mehr 
verwendet.  Über unnötige Klammern wird noch gestritten :-)
1
if ((c % 13) == 0) SchiessMirInsKnie();
2
// wird zu
3
if (c % UART_BUFFER_SIZE == 0) IstBesserLesbarSo();
Makros sind meiner Meinung nach in Ordnung, wenn man damit was macht was 
in reinem C nicht geht.  Der Präprozessor ist das eigentlich geniale 
Ding in C, der macht die Sprache praxistauglich.  Damit geht mehr als 
mit Templates in C++ auf Kosten der Typsicherheit.
Aber schämen musst du dich deswegen nicht. Wie immer gilt: Es muss erst 
mal funktionieren.

von Oliver S. (oliverso)


Lesenswert?

Udo K. schrieb:
> Es muss erst mal funktionieren.

Wenn verständlicher, robuster und wartbarer Code keine Rolle spielt, 
kann man das so sehen.

Oliver

von Axel R. (axlr)


Lesenswert?

Dann definieren wir mal für eine RGB-LED die drei RGB-Werte für die 
Farbe "PINK" bei einem Arduino mega2560. Musste ich dann in "ALTROSA" 
umtaufen. Ging halt nicht. Alle anderen Farben ließen sich definieren. 
Darauf komme erstmal einer.
Soviel zu Makros. Danach schaut man dann gehauer hin.

von Udo K. (udok)


Lesenswert?

Arduino F. schrieb:
> Ich bin in den moderneren C Eigenheiten nicht ganz so fit wie in C++...
> In C++ ist es mittlerweile so, dass man Code in *.h Dateien unterbringen
> kann. Ohne define.
> In dem man Funktionen als static oder inline deklariert.
> Kann C das mittlerweile auch?

Das ist eine richtig üble Entwicklung in C++, die zum Glück wieder 
rückläufig ist dank LTO.  Du hast kein klar definiertes Interface mehr, 
sondern ein Mischmasch aus externen Deklarationen, und  vom Modul intern 
verwendeten Funktionen, dazu eine Wurscht aus unlesbarem Code mit 
schlechter Formatierung und automatisch generierter Dokumentation als 
Draufgabe.  Die Idee eines Moduls wird dadurch zu Grabe getragen: 
Kapselung und Wiederverwendbarkeit von Code.  Also trenn sowas auf in 
*.h (Deklarationen für Anwender), *.hpp (der Template und Inline Mist) 
und *.cpp (wird immer weniger).

von Udo K. (udok)


Lesenswert?

Oliver S. schrieb:
> Udo K. schrieb:
>> Es muss erst mal funktionieren.
>
> Wenn verständlicher, robuster und wartbarer Code keine Rolle spielt,
> kann man das so sehen.

Klar sind das alles erstrebenswerte Ziele, aber der Zweck eines 
Programms ist die Funktion.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

>  Damit geht mehr als mit Templates in C++
Aua!

> auf Kosten der Typsicherheit.
Wen Typsicherheit nicht interessiert....


Soweit mir bekannt ist die "Template engine" Turing vollständig.
Der Präprozessor nicht.

von Oliver S. (oliverso)


Lesenswert?

Udo K. schrieb:
> Oliver S. schrieb:
>> Udo K. schrieb:
>>> Es muss erst mal funktionieren.
>>
>> Wenn verständlicher, robuster und wartbarer Code keine Rolle spielt,
>> kann man das so sehen.
>
> Klar sind das alles erstrebenswerte Ziele, aber der Zweck eines
> Programms ist die Funktion.

Wenns nicht mehr als die blinkende LED am Mikroprozessor sein soll, 
vielleicht. Ansonsten ist die reine Funktion zwar eine notwendige, aber 
keine hinreichende Bedingung für ein Stück Software.

Oliver

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

> Template und Inline Mist

Ich bevorzuge in C++ *.h only, verzichte wenn möglich auf *.cpp
u.A. wegen: Denn so sind alle Methoden per default inline.

Deine Abwertung "Template Mist", zeigt sehr schön deine Gesinnung.
Ich halte, deine Wertung define vs. Template für gründlich daneben.
Wie auch immer, du musst damit leben, nicht ich, also mach mal weiter 
so.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ralph S. schrieb:
> Na ja, PC0_set ist ein Makro von mir, aaaaaber dieses ruft seinerseits
> wieder ein Makro aus CH32FUN auf, von dem ich dachte, dass es eine
> Funktion und nicht selbst ein Makro ist (Fehler by me).

In ch32fun.h, Zeile 895 sind die geschweiften Klammern und das Semikolon
überflüssig und schädlich
1
#define funDigitalWrite( pin, value ) { GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)); }

Also besser so:
1
#define funDigitalWrite( pin, value ) GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf))

Um das Makro ohne Probleme auch als Teilausdruck innerhalb eines
übergeordneten Ausdrucks verwenden zu können (was aber selten sinnvoll
ist), setzt man das Ganze am besten noch in runde Klammern.
1
#define (funDigitalWrite( pin, value ) GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)))

Den do-while(0)-Trick oder ({...}) braucht man hier nicht, da das Makro
nur eine einzelne Anweisung enthält:

von Harald K. (kirnbichler)


Lesenswert?

Arduino F. schrieb:
> Ich bin in den moderneren C Eigenheiten nicht ganz so fit wie in C++...
> In C++ ist es mittlerweile so, dass man Code in *.h Dateien unterbringen
> kann. Ohne define.
> In dem man Funktionen als static oder inline deklariert.
> Kann C das mittlerweile auch?

Das kann C praktisch schon immer.

In C++ aber kann auch die Implementierung einer Memberfunktion (weder 
static noch inline) einer Klasse in einer Headerdatei untergebracht 
werden.

inline zu nutzen ist halt ein Fall von Optimierungsbemühungen; 
Funktionen als static in einer Headerdatei zu definieren, sorgt für 
aufgeblähten Code (da die Funktionen in jede "translation unit", die die 
Headerdatei einbindet, hineinkopiert werden). Gut, das kann der 
Optimierer dann wieder aufräumen ...

Als guten Stil betrache nicht nur ich so etwas nicht, nicht in C.

Aber da sehe ich auch die Verwendung von Macros, insbesondere mehrfach 
geschachtelte Macros nicht als guten Stil an.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Axel R. schrieb:
> Dann definieren wir mal für eine RGB-LED die drei RGB-Werte für die
> Farbe "PINK" bei einem Arduino mega2560. Musste ich dann in "ALTROSA"
> umtaufen. Ging halt nicht. Alle anderen Farben ließen sich definieren.
> Darauf komme erstmal einer.
> Soviel zu Makros. Danach schaut man dann gehauer hin.

Dieses Problem (mehrfach belegte Symbole, neudeutsch "name clash") ist
nicht auf Makros beschränkt, sondern kann bspw. auch bei Variablen- und
Funktionsnamen auftreten.

Udo K. schrieb:
> Der Präprozessor ist das eigentlich geniale Ding in C, der macht die
> Sprache praxistauglich.  Damit geht mehr als mit Templates in C++ auf
> Kosten der Typsicherheit.

Arduino F. schrieb:
>>  Damit geht mehr als mit Templates in C++
> Aua!

Die richtig guten Makros gibt es sowieso nur in Lisp. Die können
praktisch alles, was C-Makros und C++-Templates können, aber noch sehr,
sehr viel mehr :)

von Daniel A. (daniel-a)


Lesenswert?

Yalu X. schrieb:
> Um das Makro ohne Probleme auch als Teilausdruck innerhalb eines
> übergeordneten Ausdrucks verwenden zu können (was aber selten sinnvoll
> ist), setzt man das Ganze am besten noch in runde Klammern.
> #define (funDigitalWrite( pin, value ) GpioOf( pin )->BSHR =
> 1<<((!(value))*16 + ((pin) & 0xf)))

Deine runden Klammern sind am falschen Ort.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Daniel A. schrieb:
> Deine runden Klammern sind am falschen Ort.

Danke für den Hinweis! Es sollte natürlich so lauten:
1
#define funDigitalWrite( pin, value ) (GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)))

von Udo K. (udok)


Lesenswert?

Arduino F. schrieb:
> Deine Abwertung "Template Mist", zeigt sehr schön deine Gesinnung.
> Ich halte, deine Wertung define vs. Template für gründlich daneben.
> Wie auch immer, du musst damit leben, nicht ich, also mach mal weiter
> so.

Das Problem mit Templates ist halt das sie unleserlich sind.  Schau 
einfach mal in die STL rein, wenn du es nicht glaubst.  Makros haben 
dasselbe Problem. Hätte C++ die wichtigen Typen wie vector, array und 
string als eingebaute Typen festgelegt, gäbe es viele viele graue Haare 
weniger.

Arduino F. schrieb:
> Soweit mir bekannt ist die "Template engine" Turing vollständig.
> Der Präprozessor nicht.

Der Präprozessor ist Turing Complete, wenn auch mit vielen Verrenkungen.
Und der Präprozessor muss sich nicht an die C Regeln halten, man kann 
also noch viel mehr damit anstellen :-)

von Peter D. (peda)


Lesenswert?

Axel R. schrieb:
> Dann definieren wir mal für eine RGB-LED die drei RGB-Werte für die
> Farbe "PINK" bei einem Arduino mega2560. Musste ich dann in "ALTROSA"
> umtaufen. Ging halt nicht.

Einfach die Fehlermeldung lesen, die stößt Dich direkt mit der Nase auf 
Deinen Fehler.
Du kannst ja #undef verwenden, dann geht es auch. Wenn Port K nur 
Ausgang ist, brauchst Du ja PINK nicht.

Die Compilerbauer geben sich schon große Mühe, sinnvolle Fehlermeldungen 
zu erzeugen.
Wir hatte mal einen Programmierer für unsere Anlage, der hat fast alle 
Fehler auf "Insufficient Water Cooling" geleitet. Das wurde dann zum 
Running Gag, d.h. daran lag es nie. Wenn ein Kunde uns dieses 
Fehlermeldung durchsagte, mußte immer ein Servicetechniker ausrücken.

von Axel R. (axlr)


Lesenswert?

Peter D. schrieb:
> Einfach die Fehlermeldung lesen, die stößt Dich direkt mit der Nase auf
> Deinen Fehler.
Man hätte die komplette Fehlermeldung damals lesen sollen, stimmt!
Schon der Verweis auf die io.h, die pgmspace.h und die Arduino.h hätte 
einem zu Denken geben müssen.
Ich hatte mich seinerzeit nur über das volatile und die fehlende Klammer 
gewundert.

1
static const uint16_t PINK   = 0xF81F;
1
In file included from c:\arduino_portable_1.8.13\portable\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\io.h:99:0,
2
                 from c:\arduino_portable_1.8.13\portable\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\pgmspace.h:90,
3
                 from C:\Arduino_portable_1.8.13\portable\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:28,
4
                 from C:\Users\ar\AppData\Local\Temp\arduino_build_25786\sketch\LHM600_11.ino.cpp:1:
5
LHM600_11:35:23: error: expected unqualified-id before 'volatile'
6
 static const uint16_t PINK   = 0xF81F;
7
                       ^
8
LHM600_11:35:23: error: expected ')' before 'volatile'
9
LHM600_11:35:23: error: expected ')' before 'volatile'
ja, mit "#undef PINK" funktioniert es, weil wir das PIN-Register vom 
PortK tatsächlich nicht brauchen. Nice. ;)
1
#undef PINK
2
static const uint16_t PINK   = 0xF81F;
1
Der Sketch verwendet 28262 Bytes (11%) des Programmspeicherplatzes. Das Maximum sind 253952 Bytes.
Besten Dank, wäre ich selbst nicht drauf gekommen, das so zu lösen.
Bei mir tat es halt "ALTROSA", was ich als pragmatische Lösung empfand.

Beitrag "Arduino "static const uint16_t PINK= 0xF81F" failed"

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Harald K. schrieb:
> In C++ aber kann auch die Implementierung einer Memberfunktion (weder
> static noch inline) einer Klasse in einer Headerdatei untergebracht
> werden.
Eine solche Methode ist implizit inline.

> inline zu nutzen ist halt ein Fall von Optimierungsbemühungen;
Dass inline wirklich inlined Code erzeugt ist eher eine historische 
Annahme.
Hat mit der heutigen (C++)Bedeutung von inline wenig zu tun.

https://en.cppreference.com/w/cpp/language/inline.html

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Axel R. schrieb:
> Man hätte die komplette Fehlermeldung damals lesen sollen, stimmt!

Die Fehlermeldung ist umfangreicher, weil einmal ein Macro und danach 
eine Variable deklariert wird.
Ich würde daher Variablen nicht großschreiben. Man kann ja globale 
Variablen mit einem Großbuchstaben am Anfang schreiben "Pink".

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Peter D. schrieb:
> Man kann ja globale
> Variablen mit einem Großbuchstaben am Anfang schreiben "Pink".
Schwierig.

Ich weiß, dass es verschiedene Ansichten zu gutem Stil gibt.
Somit auch gerne Streit darüber.

Mein Vorschlag:
Variablen-, Methoden- und Funktionsbezeichner beginnen mit einem 
Kleinbuchstaben.
Selbst definierte Typen mit einem Großbuchstaben.
Defines, komplett in Großbuchstaben.
Längere Bezeichner in KamelHöckerSchreibweise.
Auf Unterstriche ganz verzichten.

Der letzte Punkt mag für C anders aussehen, wenn man Module baut.
z.B. alle Gui Dinge mit einem gui_ beginnen lassen. (gui_init())
Für C++ verwendet man da eher die Geltungsbereiche der Klassen oder 
Namespaces

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Arduino F. schrieb:
> Ich bin in den moderneren C Eigenheiten nicht ganz so fit wie in C++...
> In C++ ist es mittlerweile so, dass man Code in *.h Dateien unterbringen
> kann. Ohne define.
> In dem man Funktionen als static oder inline deklariert.
> Kann C das mittlerweile auch?

Ja, aber das mit dem inline ist ein hochmodernes Feature. Das gibt es im 
C-Standard erst seit 26 Jahren, ist also noch ganz frisch. Ganz anders 
bei C++, wo das schon ein Jahr länger standardisiert ist.

Yalu X. schrieb:
> 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.

Das ist nach Standard auch gar nicht der Effekt von "inline", auch wenn 
die Intention natürlich ist, damit das inlining zu ermöglichen.

> 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.

Doch, es macht einen Unterschied. Mit "inline" wird die 
one-definition-Rule außer Kraft gesetzt. Es darf im Programm auch ohne 
static mehr als eine Definition der Funktion geben, solange die 
Definitionen alle gleich sind.
Es gibt übrigens bei gcc auch das Attribut gnu::always inline, mit 
dem man das Inlining tatsächlich forcieren kann (sofern möglich).

Udo K. schrieb:
> Der Präprozessor ist das eigentlich geniale
> Ding in C, der macht die Sprache praxistauglich.  Damit geht mehr als
> mit Templates in C++ auf Kosten der Typsicherheit.

C++ hat recht viel Aufwand getrieben, um Makros weitgehend überflüssig 
zu machen. Heute gibt's nur wenige Fälle, in denen man die noch braucht.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Rolf M. schrieb:
> C++ hat recht viel Aufwand getrieben, um Makros weitgehend überflüssig
> zu machen. Heute gibt's nur wenige Fälle, in denen man die noch braucht.

Das ist wohl so.

#include wird noch gebraucht und z.B. #ifdef um zwischen den 
verschiedenen µC/µP zu unterscheiden.
Aber das wars dann wohl auch schon so ziemlich.

Nachtrag: #pragma once

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Rolf M. schrieb:
>> 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.
>
> Doch, es macht einen Unterschied. Mit "inline" wird die
> one-definition-Rule außer Kraft gesetzt.

Das ist IMHO aber nur in C++ so. Oder in C mittlerweile auch?

Sinnvoll ist dieses Feature eigentlich nur dann, wenn man die Funktion
auch in Übersetzungseinheiten (nicht ingelinet) aufrufen möchte, die die
Funktjonsdefinition nicht kennen. Sonst kann die One-Definition-Rule
auch ganz einfach mit einem "static" davor erfüllt werden, was ja
meistens auch gemacht wird.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Yalu X. schrieb:
> Das ist IMHO aber nur in C++ so.

Das ist auch mein bisheriger Stand.
Daher auch meine vorherige Frage.

Worauf dann eine der Antworten war:
Harald K. schrieb:
> Das kann C praktisch schon immer.
Und das stimmt eben nicht!


Gut, vielleicht war meine Frage auch nicht exakt genug gestellt.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Yalu X. schrieb:
> Rolf M. schrieb:
>>> 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.
>>
>> Doch, es macht einen Unterschied. Mit "inline" wird die
>> one-definition-Rule außer Kraft gesetzt.
>
> Das ist IMHO aber nur in C++ so. Oder in C mittlerweile auch?

Nein, in C ist es etwas anders. Meinem Verständnis nach läuft das so: 
inline wirkt da im Bezug auf die Linkage eher so ähnlich wie static. Man 
muss sich aber von Hand darum kümmern, dass im Programm eine (und genau 
eine) nicht-inline-Version der Funktion existiert, für den Fall, dass 
der Compiler es doch nicht inlinen will.

> Sinnvoll ist dieses Feature eigentlich nur dann, wenn man die Funktion
> auch in Übersetzungseinheiten (nicht ingelinet) aufrufen möchte, die die
> Funktjonsdefinition nicht kennen. Sonst kann die One-Definition-Rule
> auch ganz einfach mit einem "static" davor erfüllt werden, was ja
> meistens auch gemacht wird.

Das static hat auch den Vorteil, dass der Compiler nicht noch zusätzlich 
eine nicht-inline-Version der Funktion generieren muss, für den Fall, 
dass sie doch mal von außen aufgerufen wird. Ohne static muss der 
Compiler das ja möglich machen. Auf der anderen Seite: Wenn der Compiler 
nicht inlinet, hat jede Übersetzungseinheit nachher eine eigene Kopie 
der Funktion.

Arduino F. schrieb:
> Rolf M. schrieb:
>> C++ hat recht viel Aufwand getrieben, um Makros weitgehend überflüssig
>> zu machen. Heute gibt's nur wenige Fälle, in denen man die noch braucht.
>
> Das ist wohl so.
>
> #include wird noch gebraucht

Das ist kein Makro. Aber seit C++20 gibt's ja auch Module im Standard, 
mit denen auch #include überflüssig wird. Die scheinen aber noch nicht 
viel in Verwendung zu sein.

> und z.B. #ifdef um zwischen den verschiedenen µC/µP zu unterscheiden.

Davon könnte man wahrscheinlich auch einiges per "if constexpr" machen.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Rolf M. schrieb:

> Das ist kein Makro. Aber seit C++20 gibt's ja auch Module im Standard,
> mit denen auch #include überflüssig wird. Die scheinen aber noch nicht
> viel in Verwendung zu sein.

Laut meines Wissens war das für C++20 vorgesehen, kam mit C++23 und ist 
noch nicht fertig. Die gesamte STL muss noch überarbeitet werden. Mit 
Modulen wird jedenfalls vieles ganz anders werden. :-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Arduino F. schrieb:
> Soweit mir bekannt ist die "Template engine" Turing vollständig.

Wobei die Frage ist, ob das ein Vorteil ist.

Immerhin war es noch nicht einmal den Schöpfern klar, dass das Monster, 
das sie da geschaffen hatten, Turing-vollständig ist.  Das wurde erst 
später "entdeckt", und soweit ich weiß nicht mal von den Entwicklern 
selbst.

Arduino F. schrieb:
> In dem man Funktionen als static oder inline deklariert.
> Kann C das mittlerweile auch?

static gab es schon immer in C.

Inline ist seit C99 im Standard, wobei Compiler wie GCC inline schon 
viel früher als Spracherweiterung zB in GNU-C unterstützten.

In C99 gibt es sogar 2 Varianten: static inline und extern inline.

Und in GCC gibt es noch die 3. Variante gnu_inline, welche in GCC die 
Semantik von extern inline war bevor C99 mit einer anderen Semantik um 
die Ecke kam.

gnu_inline ist m.E. wesentlich nützlicher als extern inline, zum 
Beispiel implementiert die AVR-LibC strlen() folgendermaßen:
1
extern __ATTR_ALWAYS_INLINE__ __ATTR_GNU_INLINE__
2
size_t strlen (const char *__s)
3
{
4
  if (__builtin_constant_p (__builtin_strlen (__s)))
5
    {
6
      return __builtin_strlen (__s);
7
    }
8
  else
9
    {
10
      register const char *__r24 __asm("24") = __s;
11
      register size_t __res __asm("24");
12
      __asm ("%~call strlen" : "=r" (__res) : "r" (__r24))
13
             : "30", "31", "memory");
14
      return __res;
15
    }
16
}
Und nein, das ist kein rekursiver Aufruf :-)

Der Grund ist, dass Code wie
1
int fun1 (const char *s, int c)
2
{
3
    return c + strlen (s);
4
}

übersetzt wird zu
1
fun1:
2
/* #APP */
3
  rcall strlen
4
/* #NOAPP */
5
  add r24, r22
6
  adc r25, r23
7
  ret
anstatt zu
1
fun1:
2
  push r28
3
  push r29
4
  movw r28, r22
5
  rcall strlen
6
  add r24, r28
7
  adc r25, r29
8
  pop r29
9
  pop r28
10
  ret

Und zur besseren Kontrolle von (partiellem) Inlining gibt es im GCC 
nicht nur noinline, gnu_inline und always_inline, sondern auch noch 
flatten, noclone und noipa.

von Jörg G. (tropenhelmut)


Lesenswert?

Kann mir mal jemand diesen Satz erklären:

  "Die Makroargumente werden genau ein einziges Mal ausgewertet, wie
   dies auch bei einem Funktionsaufruf der Fall ist."

Warum soll/darf in einem C-Funktionsaufruf ein Argument nur einmal 
ausgewertet werden?

von Udo K. (udok)


Lesenswert?

Denk mal an f(i++) oder an f(ResetAfter2ndCall())...

von Bruno V. (bruno_v)


Lesenswert?

Jörg G. schrieb:
> Warum soll/darf in einem C-Funktionsaufruf ein Argument nur einmal
> ausgewertet werden?

weil x++ sonst mehrfach ausgeführt wird.

Wenn x vorher 1 ist, ist es nachher überraschender-Weise 3 oder mehr.

Das gleiche Problem, wenn das Argument einen Funktionsaufruf beinhaltet.

von Veit D. (devil-elec)


Lesenswert?

Johann L. schrieb:
> Arduino F. schrieb:
>> Soweit mir bekannt ist die "Template engine" Turing vollständig.
>
> Wobei die Frage ist, ob das ein Vorteil ist.

Hallo Johann,

warum das soll das ein Nachteil sein? Die Sprache C/C++ ist generell 
komplett Turing fähig. Egal ob mit oder ohne Template Programmierung. 
Turing-Vollständigkeit besagt nur, dass man alle Rechenaufgaben mit 
dieser Sprache lösen kann. Mit Template Programmierung verlagert man 
diese Berechnungen in die Compilezeit. Okay, damit dauert die 
Kompilierung länger. Dafür hat man zur Laufzeit Rechenzeit 
freigeschaufelt. Ist in meinen Augen ein Vorteil. Zusätzlich bleibt auch 
das kompilierte Programm im Vergleich kleiner.

> Immerhin war es noch nicht einmal den Schöpfern  klar, dass das Monster,
> das sie da geschaffen hatten, Turing-vollständig ist.  Das wurde erst
> später "entdeckt", und soweit ich weiß nicht mal von den Entwicklern
> selbst.

Diese Aussage hat auch so einen negativen Touch. Warum? Ist auch nicht 
weiter schlimm, wenn die Fähigkeit eines "Projekts" erst später erkannt 
werden. Man kann ja nicht alles immer gleich überblicken. Das zeigt mir 
jedoch eines. Das die Basis von C/C++ schon durchdacht begonnen wurde, 
sonst wäre das nicht möglich gewesen.

von Jörg G. (tropenhelmut)


Lesenswert?

Udo K. schrieb:
> Denk mal an f(i++) oder an f(ResetAfter2ndCall())...

Das zweite ist mir ersichtlich, aber das erste versteh ich nicht.
Mit
1
#include <stdio.h>
2
3
void Test(int x);
4
5
int main()
6
{ 
7
  int x = 3;
8
  Test(x++);
9
  return(0);
10
}
11
12
void Test(int x)
13
{
14
  printf("x: %d\n", x);
15
  printf("x: %d\n", x);
16
  return;
17
}

wird erwartungsgemäß

  x: 3

  x: 3

ausgegeben
Gibt es ein konkretes Beispiel? Gibt es zu dem Thema allgemein was im 
Internet?

OT: Kann man im Forum eigentlich einen Zeilenumbruch erzwingen?
Bei mir werden die normal eingetippten ignoriert (so wie dieser gerade).

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

1
#include <stdio.h>
2
3
#define Test(x) \
4
  printf("x: %d\n", x); \
5
  printf("x: %d\n", x); \
6
  printf("x: %d\n", x); \
7
  printf("x: %d\n", x); \
8
  printf("x: %d\n", x); \
9
  printf("x: %d\n", x); 
10
11
int main()
12
{ 
13
  int x = 3;
14
  Test(x++);
15
  return(0);
16
}

von Harald K. (kirnbichler)


Lesenswert?

Jörg G. schrieb:
> OT: Kann man im Forum eigentlich einen Zeilenumbruch erzwingen?
> Bei mir werden die normal eingetippten ignoriert (so wie dieser gerade).

Mobilbrowser?

Im richtigen gehts.

von Jörg G. (tropenhelmut)


Lesenswert?

Harald K. schrieb:
> Jörg G. schrieb:
>> OT: Kann man im Forum eigentlich einen Zeilenumbruch erzwingen?
>> Bei mir werden die normal eingetippten ignoriert (so wie dieser gerade).
>
> Mobilbrowser?
>
> Im richtigen gehts.

Nein, Firefox unter Windows!

von Udo K. (udok)


Lesenswert?

>Gibt es ein konkretes Beispiel? Gibt es zu dem Thema allgemein was im Internet?

Ich war mal wieder zu langsam, aber egal:
1
#include <stdio.h>
2
3
#define Min(a,b) ((a) < (b) ? (a) : (b))
4
5
int main()
6
{ 
7
    int x = 3;
8
    printf("x: %d\n", Min(x++, 4));
9
    return(0);
10
}

: Bearbeitet durch User
von Jörg G. (tropenhelmut)


Lesenswert?

Arduino F. schrieb:
>
1
> 
2
> #include <stdio.h>
3
> 
4
> #define Test(x) \
5
>   printf("x: %d\n", x); \
6
>   printf("x: %d\n", x); \
7
>   printf("x: %d\n", x); \
8
>   printf("x: %d\n", x); \
9
>   printf("x: %d\n", x); \
10
>   printf("x: %d\n", x);
11
> 
12
> int main()
13
> {
14
>   int x = 3;
15
>   Test(x++);
16
>   return(0);
17
> }
18
> 
19
>

Ja, aber das ist doch ein Makro und eben keine Funktion.

Ich glaube, ich habe den Satz

"Die Makroargumente werden genau ein einziges Mal ausgewertet, wie
   dies auch bei einem Funktionsaufruf der Fall ist."

missverstanden und der zweite Satztteil bedeutet einfach, dass der 
Compiler grundsätzlich zu Beginn einer Funktion das Argument einmal 
auswertet (normalerweise in ein Register schreibt) und es dann bei 
mehrfachen Lesezugriffen innerhalb der Funktion selbstverständlich 
diesen Wert behält (anders als eben bei einem funktionsähnlichen Makro, 
s.o. Dein Beispiel) und nicht, dass der Programmierer irgendwas beachten 
muss.

von Rolf M. (rmagnus)


Lesenswert?

Veit D. schrieb:
> Mit Template Programmierung verlagert man diese Berechnungen in die
> Compilezeit. Okay, damit dauert die Kompilierung länger. Dafür hat man
> zur Laufzeit Rechenzeit freigeschaufelt. Ist in meinen Augen ein Vorteil.

Template-Metaprogramming ist aber prima für den ioccc geeignet. 
Inzwischen gibt's für eine etwas weniger hirnknotenverursachende 
Schreibweise auch consteval-Funktionen.

Harald K. schrieb:
> Jörg G. schrieb:
>> OT: Kann man im Forum eigentlich einen Zeilenumbruch erzwingen?
>> Bei mir werden die normal eingetippten ignoriert (so wie dieser gerade).
>
> Mobilbrowser?
>
> Im richtigen gehts.

Es geht, allerdings zeigt die Vorschau es falsch an.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Jörg G. schrieb:
> Ich glaube, ich habe den Satz
> ...
> missverstanden
Das denke ich auch.

Das letzte und das Eingangsbeispiel zeigen 2 perfekte Möglichkeiten sich 
mit Macros ins eigene Knie zu schießen.

Beide Sorten von Macros kann man jahrelang einsetzen, ohne dass es 
Probleme gibt, aber ändern sich die Einsatzbedingungen, gehts ins Knie.
Bei der Fehlersuche ist man sich sicher, dass die Macros funktionieren, 
werden so oft spät in Frage gestellt.
Der Trend, diese wie Funktionen aussehen zu lassen, verschärft das 
Problem eher, als dass es Lösungen anbietet.

Sicherlich kann man beide Böcke mit geschickt formulierten Dingen 
vermeiden, aber es sind und bleiben einfache Textersetzungen, die keine 
Datentypen sehen, oder gar von einander unterscheiden können.

von Bruno V. (bruno_v)


Lesenswert?

Jörg G. schrieb:
> nicht, dass der Programmierer irgendwas beachten muss.

Ich hatte das eben so verstanden, dass der Programmierer genau darauf 
achten soll: --> Schreibe Makros immer so, dass Argumente nur genau 
einmal ausgewertet werden (und nicht so, wie in den Beispielen hier, die 
das Problem verdeutlichen).

Es ist meist möglich. Die meisten Programmierer von Makros lassen ihre 
Nutzer eher aus Nachlässigkeit in diese Falle tappen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bruno V. schrieb:
> Es ist meist möglich. Die meisten Programmierer von Makros lassen ihre
> Nutzer eher aus Nachlässigkeit in diese Falle tappen.

Wobei der Nutzer auch die Dokumentation lesen könnte.

Und zum "meist möglich": Dazu braucht es idR nicht-Standard 
Erweiterungen. Hier ein GCC Beispiel mit valued Blocks und typeof:

Anzumerken ist, dass typeof sein Argument nicht auswertet.
1
#define MAX(a, b)                               \
2
    (__extension__({                            \
3
            __typeof__(a) _a = (a);             \
4
            __typeof__(b) _b = (b);             \
5
            _a > _b ? _a : _b;                  \
6
    }))
7
8
int use_max (int a, int b)
9
{
10
    int c = MAX (a++, b++);
11
    return a + b + c;
12
}
13
14
int use_use_max (void)
15
{
16
    return use_max (1, 2); // return 7
17
}

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Johann L. schrieb:
> Und zum "meist möglich": Dazu braucht es idR nicht-Standard
> Erweiterungen. Hier ein GCC Beispiel mit valued Blocks und typeof:
>
> Anzumerken ist, dass typeof sein Argument nicht auswertet.
1
 #define MAX(a, b)                               \
2
    (__extension__({                            \
3
            __typeof__(a) _a = (a);             \
4
            __typeof__(b) _b = (b);             \
5
            _a > _b ? _a : _b;                  \
6
    }))

Das vereinigt dann alle Nachteile, außer diesem einen. Sonst heißt es 
immer, "portabel ist wichtig". Warum macht man das? Ja, klar, weil man 
es kann, als sportliche Herausforderung oder um Kollegen zu ärgern.

Was war eigentlich zuerst da, fgetc() als Funktion oder getc() als 
Macro? War getc() jemals in irgendeiner Hinsicht besser? Geschwindigkeit 
kann es in dem Fall ja nicht gewesen sein und Bytes spart es auch nicht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> Johann L. schrieb:
>> Und zum "meist möglich": Dazu braucht es idR nicht-Standard
>> Erweiterungen. Hier ein GCC Beispiel mit valued Blocks und typeof:
>>
>> Anzumerken ist, dass typeof sein Argument nicht auswertet.
1
>> #define MAX(a, b)                               \
2
>>     (__extension__({                            \
3
>>             __typeof__(a) _a = (a);             \
4
>>             __typeof__(b) _b = (b);             \
5
>>             _a > _b ? _a : _b;                  \
6
>>     }))
>
> Das vereinigt dann alle Nachteile, außer diesem einen. Sonst heißt es
> immer, "portabel ist wichtig". Warum macht man das? Ja, klar, weil man
> es kann, als sportliche Herausforderung oder um Kollegen zu ärgern.

Nein.  Lies einfach mal den Beitrag, auf welchen der Code Teil der 
Anwort ist.  Es ist ein konkretes Beispie dafür, dass es eben nicht so 
einfach ist, ein Makro funktionsähnlich zu machen.  MAX ist ja nicht so 
unüblich.

Zum Code selbst:  Portierbarkeit bekommt man mit #ifdef__GNUC__.  Die 
verwendeten Spracherweiterunge sind durchaus sehr nützlich, etwa zur 
Verwendung in System-Headern.   Und da geht es in erster Linie um 
Funktionalität und nicht um Schönheit.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Johann L. schrieb:
> etwa zur
> Verwendung in System-Headern.   Und da geht es in erster Linie um
> Funktionalität und nicht um Schönheit.
Diese Sicht hat gewisse Ähnlichkeit mit der irgendwo oben benannten 
Unübersichtlichkeit der Templates in der Libstdc++.
Auch dort ist Schönheit nicht das oberste Ziel, eher Performance und 
Nutzbarkeit.

von Harald K. (kirnbichler)


Lesenswert?

Johann L. schrieb:
> Portierbarkeit bekommt man mit #ifdef__GNUC__.

Naja, "Portierbarkeit", die dann darin besteht, daß das Konstrukt mit 
anderen Compilern nicht funktioniert ...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Harald K. schrieb:
> Johann L. schrieb:
>> Portierbarkeit bekommt man mit #ifdef__GNUC__.
>
> Naja, "Portierbarkeit", die dann darin besteht, daß das Konstrukt mit
> anderen Compilern nicht funktioniert ...

Irgendeinen Tod musst du sterben.

Entweder anderen Compiler bietet ähnliche Feature, oder das Feature 
selbst ist schicht und einfach nicht portabel -- in dem Fall hätte man 
besser gleich richtig designed.

Bei System-Header spielt Portabilität wiederum keine Rolle, weil diese 
ja Teil der Toolchain sind und somit auf den Compiler passen.  (Es sei 
denn mann ist Clang und behauptet man wäre kompatibel zu GCC, ist es 
dann aber nicht).

: Bearbeitet durch User
von Bruno V. (bruno_v)


Lesenswert?

Johann L. schrieb:
> Es ist ein konkretes Beispie dafür, dass es eben nicht so
> einfach ist, ein Makro funktionsähnlich zu machen.  MAX ist ja nicht so
> unüblich.

Ja. Es ist nicht unüblich. Aber genau deshalb vermeiden wir diese Art 
von "Template"-Makros, die mit beliebigen Typen funktionieren. Und 
sterben den Tod einer Armada von typsicheren max-Funktionen.

von Mario M. (thelonging)


Lesenswert?

Jörg G. schrieb:
> OT: Kann man im Forum eigentlich einen Zeilenumbruch erzwingen?
> Bei mir werden die normal eingetippten ignoriert (so wie dieser gerade).

Zwei Leerzeichen ans Zeilenende, dann Enter.

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.