Forum: Mikrocontroller und Digitale Elektronik Unterschied #define und Funktion?


von tom (Gast)


Lesenswert?

Hallo,

kann mir einer von euch die Vorteile von "#define" / "Inline" (Makro) 
gegenüber einer Funktion, bzw. anderstrum erklären?

Gemeint ist folgendes:
1
#define sbi(p,n)  (p) |= (1<<n)

vs.
1
void pi (float uebergabe1)
2
{
3
 return uebergabe1 * 3.14;
4
}

Zugegeben, beide Teile machen etwas anderes (hab das schnell 
zusammenkopiert), aber man kann sowohl die PI-Berechnung als Makro als 
auch als Funktion ausführen.

Worin liegen also die einzelnen vorteile?

Danke

von Dr. Sommer (Gast)


Lesenswert?

tom schrieb:
> Hallo,
>
> kann mir einer von euch die Vorteile von "#define" / "Inline" (Makro)
> gegenüber einer Funktion, bzw. anderstrum erklären?
Ein Makro (#define) ist nur eine dumme Textersetzung die vor dem 
Compilen vorgenommen wird. Eine Funktion ist eine dem Compiler bekannte 
Einheit, bei der Typüberprüfungen bei den Argumenten und Rückgabewert 
vorgenommen werden und die einen Scope hat.
> Worin liegen also die einzelnen vorteile?
Mit Makros handelt man sich eine Menge Probleme ein, zB reserviert ein 
Makro seinen Namen global und wenn man versehentlich den Namen irgendwo 
anders noch verwendet gibts obskure Compilerfehler. inline-Funktionen 
haben den Nachteil dass sie keinen beliebigen Code generieren können, zB 
kann eine inline-Funktion keine Funktionen definieren. Dafür werden aber 
die Argumente nicht versehentlich mehrfach ausgewertet, man kann lokale 
temporäre Variablen definieren, die Typen der Argumente und Rückgabewert 
werden vom Compiler geprüft etc.
Wegen der genannten Nachteile sollte man Makros so weit wie möglich 
vermeiden und nur dann verwenden, wenn man die gleiche Funktionalität 
nicht durch inline-Funktionen erhalten kann. Das gilt im übrigen auch 
für Konstanten:
1
#define SIZE 10
ist viel gefährlicher als
1
static const size_t SIZE = 10;
und nur selten tatsächlich notwendig.

von Oliver R. (orb)


Lesenswert?

Bau mal Schleifen, Abfragen und Sprünge in ein '#define' ein.

von tom (Gast)


Lesenswert?

Danke an Dr. Sommer - ich hab's verstanden :)

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Grundsätzlich gebe ich Dr. Sommer recht, hätte aber noch ein paar 
Anmerkungen:

das Ersetzen von Makros durch inline-Funktionen setzt immer einen gut 
optimierenden Compiler voraus - hat man den nicht, können Makros 
erhebliche Geschwindigkeitsvorteile bringen. Es lohnt als an kritischen 
Stellen immer ein Blick auf den produzierten Assembler-Code. Historisch 
resultieren ja viele Makros aus nicht so guten Optimierungen

makros können selten bis nie vollständig ersetzt werden, es ist also 
wichtig dass man makros beherrscht, sie lesen kann, und auch Tricks wie 
grundsätzliches Klammern der Argumente, temporäre Variablen zur 
verhinderung der Mehrfachauswertung, sowie den do { ... } while (0) 
Ausdruck kennt.

Ein Praxisbeispiel, welches man ohne Makros nicht hinbekommt:
1
#define lcd_printf(row,format,...) __lcd_printf(row, PSTR(format), ## __VA_ARGS__)


Will man portabel programmieren (z.B. Win/Unix, oder auch nur für 
verschiedene Unix-Flavours, geht ohne #define /und #ifdef) gar nix mehr.

von Dr. Sommer (Gast)


Lesenswert?

Michael Reinelt schrieb:
> das Ersetzen von Makros durch inline-Funktionen setzt immer einen gut
> optimierenden Compiler voraus - hat man den nicht, können Makros
> erhebliche Geschwindigkeitsvorteile bringen.
Wenn der verwendete Compiler inlinen nicht beherrscht, würde ich mein 
Geld zurück verlangen und/oder GCC oder Clang verwenden...
> Es lohnt als an kritischen
> Stellen immer ein Blick auf den produzierten Assembler-Code.
Das ja.
> Historisch
> resultieren ja viele Makros aus nicht so guten Optimierungen
Oder aus Unwissen :-/
> Ein Praxisbeispiel, welches man ohne Makros nicht hinbekommt:
> #define lcd_printf(row,format,...) __lcd_printf(row, PSTR(format), ##
> _VA_ARGS_)
In C++ schon:
1
template <typename... Args>
2
inline auto lcd_printf (row, format, Args... args) -> decltype (__lcd_printf (row, format, args...)) {
3
  return __lcd_printf (row, format, args...);
4
}
Etwas mehr Schreibarbeit, viel mehr Sicherheit, viel weniger 
Überraschungen, 0 Overhead.
> Will man portabel programmieren (z.B. Win/Unix, oder auch nur für
> verschiedene Unix-Flavours, geht ohne #define /und #ifdef) gar nix mehr.
Die man hier aber hoffentlich nur als Schalter verwendet. Wobei es für 
diesen häufig auftretenden Fall auch abstrahierende Libraries gibt...

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Dr. Sommer schrieb:
> Michael Reinelt schrieb:
>> das Ersetzen von Makros durch inline-Funktionen setzt immer einen gut
>> optimierenden Compiler voraus - hat man den nicht, können Makros
>> erhebliche Geschwindigkeitsvorteile bringen.
> Wenn der verwendete Compiler inlinen nicht beherrscht, würde ich mein
> Geld zurück verlangen und/oder GCC oder Clang verwenden...

Da gehts nicht nur um inline, sondern auch um ein tiefes constant 
folding etc. ich hab jetzt (gottseidank :-) keine beispiele bei der 
Hand, aber ich hab schon jede Menge programmiert wo es ohne makros 
definitiv nicht ging (aus geschwindigkeitsgründen)

>> resultieren ja viele Makros aus nicht so guten Optimierungen
> Oder aus Unwissen :-/
oder aus gewohnheit (wie bei mir :-)

>> Ein Praxisbeispiel, welches man ohne Makros nicht hinbekommt:
>> #define lcd_printf(row,format,...) __lcd_printf(row, PSTR(format), ##
>> _VA_ARGS_)
> In C++ schon:
>
1
template <typename... Args>
2
> inline auto lcd_printf (row, format, Args... args) -> decltype 
3
> (__lcd_printf (row, format, args...)) {
4
>   return __lcd_printf (row, format, args...);
5
> }

Ich kann leider kein C++, aber wie kriegst du das PSTR() da rein?
>> Will man portabel programmieren (z.B. Win/Unix, oder auch nur für
>> verschiedene Unix-Flavours, geht ohne #define /und #ifdef) gar nix mehr.
> Die man hier aber hoffentlich nur als Schalter verwendet. Wobei es für
> diesen häufig auftretenden Fall auch abstrahierende Libraries gibt...
oder die autoconf-Hölle :-(

von Kein Name (Gast)


Lesenswert?

> das Ersetzen von Makros durch inline-Funktionen setzt immer einen
> gut optimierenden Compiler voraus

1975 hatten Kernighan und Ritchie noch keinen optimierenden Compiler. 
Damals mussten die halt Inline-Optimierungen noch irgendwie zurecht 
tricksen. Hat sich inzwischen erledigt.

von Kein Name (Gast)


Lesenswert?

... und unter den Mikrocontroller Entwicklern findest du recht viele 
Leute, die jedes Bit genau unter Kontrolle haben wollen. Die sich nicht 
drauf verlassen wollen, dass der Compiler es schon irgendwie richtig 
macht.

von Thomas (Gast)


Lesenswert?

Michael Reinelt schrieb:
> Es lohnt als an kritischen
> Stellen immer ein Blick auf den produzierten Assembler-Code.

Wobei hier "kritische Stelle" als: "Ich habe gemessen/simuliert, dass 
diese Stelle meinen Code um  x ms verlangsamt. Akzeptabel wären aber nur 
y ms, weil bei längerer Laufzeit..... " definiert ist und nicht als "Ich 
habe mal gehört, dass XY() langsam ist und habe das diffuse Gefühl, 
meinen Code irgendwie optimieren zu müssen, weil embedded und so und 
weil Makros professioneller aussehen."

von Dr. Sommer (Gast)


Lesenswert?

Michael Reinelt schrieb:
> Da gehts nicht nur um inline, sondern auch um ein tiefes constant
> folding etc. ich hab jetzt (gottseidank :-) keine beispiele bei der
> Hand, aber ich hab schon jede Menge programmiert wo es ohne makros
> definitiv nicht ging (aus geschwindigkeitsgründen)
Was fürn Compiler war denn das?
> oder aus gewohnheit (wie bei mir :-)
Hoffentlich muss dann keiner deinen Code weiterverwenden und sucht sich 
dann einen Wolf nach Makros die in irgendwelchen Headern definiert sind 
und später tretminenartig für Probleme sorgen...
> Ich kann leider kein C++, aber wie kriegst du das PSTR() da rein?
Kommt drauf an wie das mit dem PSTR funktioniert... Im Zweifelsfall 
immer im Usercode (vergessen resultiert ja hoffentlich in einem 
Compiler-Error), denn da gehört die Speicherart sowieso hin. Variadische 
Argumente weiterleiten ist jedenfalls kein Problem.

Kein Name schrieb:
> Die sich nicht
> drauf verlassen wollen, dass der Compiler es schon irgendwie richtig
> macht.
Und deren Arbeitszeit scheinbar so billig ist dass es sich lohnt jedes 
Bit einzeln zu betrachten anstelle einen richtigen Compiler zu kaufen?

Thomas schrieb:
> und weil Makros professioneller aussehen."
An Makros sieht gar nichts professionell aus, denn die sind nur eine 
dumme Textersetzung wie sie zu Zeiten der Makroassembler verwendet 
wurde. Professionell möchte man Features wie Scope & Typsystem verwenden 
um Fehler zu vermeiden/finden.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Dr. Sommer schrieb:
> Michael Reinelt schrieb:
>> ich hab schon jede Menge programmiert wo es ohne makros
>> definitiv nicht ging (aus geschwindigkeitsgründen)
> Was fürn Compiler war denn das?

hach, das ist lange her... Turbo-C, irgendein Watcom-Zeugs, vermutlich 
Intel, irgendein Ding auf einer VAX 11/780, diverse Compiler auf HP/UX, 
Irix, Digital,... frag mich lieber welcher Compiler nicht betroffen 
war :-)

> Hoffentlich muss dann keiner deinen Code weiterverwenden und sucht sich
> dann einen Wolf nach Makros die in irgendwelchen Headern definiert sind
> und später tretminenartig für Probleme sorgen...
Ach komm... man kann auch mit makros sauber programmieren. oder bist du 
ein Anhänger der "goto ist böse" Fraktion?

> Kommt drauf an wie das mit dem PSTR funktioniert... Im Zweifelsfall
> immer im Usercode (vergessen resultiert ja hoffentlich in einem
> Compiler-Error), denn da gehört die Speicherart sowieso hin.

#define PSTR(s) ((const PROGMEM char *)(s))
Vergessen liefert keinen Fehler. Und in den user-Code gehört das nicht, 
wenn der Code portabel sein soll.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Michael Reinelt schrieb:
> Ach komm... man kann auch mit makros sauber programmieren. oder bist du
> ein Anhänger der "goto ist böse" Fraktion?

Nanana..
Kein richtiger, fähiger Programmierer wird je sowas wie 'goto' als böse 
und verschmähenswert ansehen. Sowas tun nur die Halbgebildeten, die eine 
Programmiersprache auswendig gelernt haben und deshalb mental nicht über 
den Dingen stehen.

Aber: Makros sind heutzutage MIST, denn sie tragen ganz gründlich zur 
Unverständlichkeit einer Quelle bei. Schau dir mal die Quelle von 
Nuvoton's USB Handler an. Da möchte man deren Urheber am liebsten 
köpfen, dann erwürgen dann.. (frei nach Osmin)

Und im krassen Gegensatz zu unserem Dr.Dolittle sehe ich #define als 
wesentlich besser an als sein Gebräu:

Dr. Sommer schrieb:
> #define SIZE 10
> ist viel gefährlicher als
> static const size_t SIZE = 10;

Grund: ein #define wird vor dem eigentlichen Übersetzen aufgelöst und 
kann (wenn man es nicht in einen überall eingebundenen Header schreibt) 
deshalb keine Seiteneffekte in anderen Quellen haben. Ebenso belegt 
etwas, das per #define erklärt wird, keinerlei Speicherplatz und 
reserviert auch keinen Namen im Code. Bei seinem Code wird 
sinnloserweise ein Stück ROM belegt und dessen Name muß bis zum Linker 
mit durchgeschleift werden. Von der für ein reibungsloses Miteinander 
von unterschiedlichen Moduln nötigen Kapselung kann da keine Rede 
sein.

Ansonsten nur noch eines: Wer meint, ohne Makros keinen effektiven Code 
schreiben zu können ("aber ich hab schon jede Menge programmiert wo es 
ohne makros definitiv nicht ging (aus geschwindigkeitsgründen)"), hat 
seine Software strukturell "unoptimal" angelegt.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

Michael Reinelt schrieb:
> hach, das ist lange her... Turbo-C, irgendein Watcom-Zeugs, vermutlich
> Intel, irgendein Ding auf einer VAX 11/780, diverse Compiler auf HP/UX,
> Irix, Digital,... frag mich lieber welcher Compiler nicht betroffen
> war :-)
Ohgott. Damals. :D
>> Hoffentlich muss dann keiner deinen Code weiterverwenden und sucht sich
>> dann einen Wolf nach Makros die in irgendwelchen Headern definiert sind
>> und später tretminenartig für Probleme sorgen...
> Ach komm... man kann auch mit makros sauber programmieren. oder bist du
> ein Anhänger der "goto ist böse" Fraktion?
Man kann, ja, und hin und wieder sind Makros unumgänglich und goto 
praktisch. Aber wenn man sich sowas wie die CMSIS anguckt, in der 
9000000 Makros mit kurzen Namen (gefährlich) definiert sind, möchte man 
Makros lieber gleich ganz verbieten.
>> Kommt drauf an wie das mit dem PSTR funktioniert... Im Zweifelsfall
>> immer im Usercode (vergessen resultiert ja hoffentlich in einem
>> Compiler-Error), denn da gehört die Speicherart sowieso hin.
>
> #define PSTR(s) ((const PROGMEM char *)(s))
Also nur ein cast? casten kann man auch in C++:
1
template <typename... Args>
2
inline auto lcd_printf (row, format, Args... args) -> decltype (__lcd_printf (row, format, args...)) {
3
  return __lcd_printf (row, PSTR (format), args...);
4
}

> Vergessen liefert keinen Fehler. Und in den user-Code gehört das nicht,
> wenn der Code portabel sein soll.
Aber in den LCD-Code gehört eine Angabe wo der Speicher hinkommt? Was 
wenn man doch RAM-Daten an die Funktion übergeben soll? Da würd ich 
lieber das PSTR überall wo nötig in den User-Code packen und auf 
Plattformen wo es nicht gebraucht wird es als "nichts" definieren.

W.S. schrieb:
> Grund: ein #define wird vor dem eigentlichen Übersetzen aufgelöst
Genau das ist das Problem.
> und
> kann (wenn man es nicht in einen überall eingebundenen Header schreibt)
> deshalb keine Seiteneffekte in anderen Quellen haben.
Und "static const" zum Glück auch nicht.

W.S. schrieb:
> Ebenso belegt
> etwas, das per #define erklärt wird, keinerlei Speicherplatz
W.S. schrieb:
> Bei seinem Code wird
> sinnloserweise ein Stück ROM belegt
Bei einem halbwegs schlauen Compiler (GCC) ist das alles Unsinn und das 
"static const" wirkt Speichertechnisch wie ein Literal. In C nur als 
Nettigkeit vom Compiler, in C++ vom Standard vorgeschrieben...

W.S. schrieb:
> Von der für ein reibungsloses Miteinander
> von unterschiedlichen Moduln nötigen Kapselung kann da keine Rede
> sein.
Du verstehst unter Kapselung also versteckte globale Variablen? Urks. 
Dann verstehst du unter "Objekt" auch bestimmt ".c -Datei". Jedenfalls, 
wenn man unbedingt gleich benannte aber unterschiedliche globale 
Konstanten in mehreren .c -Dateien haben will, ist das dank "static" 
eben kein Problem, da dann eben kein Linker-Symbol angelegt wird. 
Vielleicht mal schauen wie C funktioniert bevor man seinen Unsinn 
verzapft?

W.S. schrieb:
> Ansonsten nur noch eines: Wer meint, ohne Makros keinen effektiven Code
> schreiben zu können ("aber ich hab schon jede Menge programmiert wo es
> ohne makros definitiv nicht ging (aus geschwindigkeitsgründen)"), hat
> seine Software strukturell "unoptimal" angelegt.
Das ist allerdings korrekt.

von W.S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Bei einem halbwegs schlauen Compiler (GCC) ist das alles Unsinn

Schreib du mal keinen Unsinn. Wenn jemald hinschreibt

static const size_t SIZE = 10;

dann ist das eine Konstante im Bereich für konstante Daten (je nach 
System kann das ROM sein oder initialisierter RAM) und basta. Der 
Compiler hat da ein bissel die Klappe zu halten, weil er die eigentliche 
Intention des Schreibers nicht wissen kann. So eine Konstante wird 
eigentlich bei allen Systemen bis zum Linker durchgeschleppt und belegt 
auch Identifier-Platz.

" Du verstehst unter Kapselung also versteckte globale Variablen? Urks."
Nicht nur. Auch Funktionen, die nur innerhalb des Dunstkreises eines 
Moduls, Units, oder wie auch immer man einen zusammengehörigen Block 
bezeichnen möchte, vorhanden sind. Kurzum, alles was das aufrufende 
Programm nicht wirklich zu wissen braucht. Dazu gehören auch 
modulinterne  Variablen, die eben NICHT auf dem Stack angelegt sind. Da 
ist nix mit Urks.

Und deine Bemerkung über CMSIS möchte ich etwas drastischer ausdrücken: 
Man sollte diese Schaumschlägerei ganz und garnicht benutzen. Die 
Einführung von abertausenden zusätzlichen Identifiern macht das 
programmieren von µC nicht einfacher und übersichtlicher, sondern 
wirklich nur fehleranfälliger und nerviger. Ein gleiches Urteil gilt für 
die grandiosen Elaborate von ST. Es sind eben Fehlleistungen, die auf 
der Annahme beruhen, daß ein Sack von hardware-halb-unabhängigen Namen 
besser sei als sich auf das zu beschränken, was im HW-Manual deklariert 
ist.

Was man als Programmierer viel besser brauchen kann (könnte..) wären in 
sich abgeschlossene Treiber für kompliziertere Peripherie. 
Beispielsweise USB, Ethernet lowest level, SDIO. Aber was da angeboten 
wird, sind ja ebenfalls nur halbfertige NICHT in sich abgeschlossene 
Module, die immer nur einen Rumpf darstellen, der sich so wie er ist, 
nicht benutzen läßt.

W.S.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

W.S. schrieb:
> Ansonsten nur noch eines: Wer meint, ohne Makros keinen effektiven Code
> schreiben zu können ("aber ich hab schon jede Menge programmiert wo es
> ohne makros definitiv nicht ging (aus geschwindigkeitsgründen)"), hat
> seine Software strukturell "unoptimal" angelegt.

Das beantworte ich mal am besten mit deinen Worten:

W.S. schrieb:
> Sowas tun nur die Halbgebildeten, die eine
> Programmiersprache auswendig gelernt haben und deshalb mental nicht über
> den Dingen stehen.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Dr. Sommer schrieb:
> Also nur ein cast? casten kann man auch in C++:

Und jetzt gehen wir mal weg von der grauen Theorie ins sehr 
farbenprächtige, aber leider auch harte und unfaire real life: dort kann 
man sich die Sprache (C oder C++) und den Compiler nicht immer 
aussuchen.

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> Dr. Sommer schrieb:
>> Bei einem halbwegs schlauen Compiler (GCC) ist das alles Unsinn
>
> Schreib du mal keinen Unsinn. Wenn jemald hinschreibt
>
> static const size_t SIZE = 10;
>
> dann ist das eine Konstante im Bereich für konstante Daten (je nach
> System kann das ROM sein oder initialisierter RAM) und basta. Der
> Compiler hat da ein bissel die Klappe zu halten, weil er die eigentliche
> Intention des Schreibers nicht wissen kann. So eine Konstante wird
> eigentlich bei allen Systemen bis zum Linker durchgeschleppt und belegt
> auch Identifier-Platz.
Schauen wir uns das doch mal im konkreten Beispiel an. Dieser Code:
1
#include <stdint.h>
2
3
static const uint8_t SIZE = 10;
4
5
uint8_t getVal () {
6
        return SIZE;
7
}
wird mit "avr-gcc test.c -o test.o -O1" compiled und mit "avr-objdump -d 
test.o" disassemblisiert. Es kommt heraus:
1
00000000 <getVal>:
2
   0:  8a e0         ldi  r24, 0x0A  ; 10
3
   2:  08 95         ret
Oh Schreck, die Konstante liegt überhaupt nicht seperat im ROM, sondern 
wurde vom Compiler in die Instruktion hineinoptimiert! Schauen wir uns 
mit "avr-nm test.o" die generierten Linker-Symbole an, ist weit und 
breit nichts von "SIZE" zu sehen. Das ändert sich wenn man das "static" 
weglässt. Denn "static" bei der Definition globaler Variablen oder 
Funktionen bedeutet nichts anderes, als kein Linkersymbol anzulegen...
>
> " Du verstehst unter Kapselung also versteckte globale Variablen? Urks."
> Nicht nur. Auch Funktionen, die nur innerhalb des Dunstkreises eines
> Moduls, Units, oder wie auch immer man einen zusammengehörigen Block
> bezeichnen möchte, vorhanden sind. Kurzum, alles was das aufrufende
> Programm nicht wirklich zu wissen braucht. Dazu gehören auch
> modulinterne  Variablen, die eben NICHT auf dem Stack angelegt sind. Da
> ist nix mit Urks.
Du solltest mal eine objektorientierte Sprache lernen. Dort lernst du 
was Kapselung wirklich bedeutet.
>
> Und deine Bemerkung über CMSIS möchte ich etwas drastischer ausdrücken:
> Man sollte diese Schaumschlägerei ganz und garnicht benutzen. Die
> Einführung von abertausenden zusätzlichen Identifiern macht das
> programmieren von µC nicht einfacher und übersichtlicher, sondern
> wirklich nur fehleranfälliger und nerviger.
Das Problem ist nur wie sie definiert sind, nämlich als Makros. Wären 
sie schön als Variablen/Konstanten definiert könnte man wenigstens C++ 
verwenden, ein "namespace XX { ... }" um das #include packen und damit 
diese Identifier in eine dunkle Ecke schieben. Aber an sowas denken die 
Herren E-Techniker & Hardwareentwickler bei ARM und ST nicht. Dass man 
eine Menge Identifier braucht ist leider unumgänglich - wenn man 1000 
Register hat, braucht man nunmal 1000 Namen dafür... Und es ist ja nicht 
so dass andere API's nicht noch viel mehr davon hätten...
> Was man als Programmierer viel besser brauchen kann (könnte..) wären in
> sich abgeschlossene Treiber für kompliziertere Peripherie.
> Beispielsweise USB, Ethernet lowest level, SDIO. Aber was da angeboten
> wird, sind ja ebenfalls nur halbfertige NICHT in sich abgeschlossene
> Module, die immer nur einen Rumpf darstellen, der sich so wie er ist,
> nicht benutzen läßt.
Das USB-Zeug von denen lässt sich schon nutzen. Aber es hat sogar einen 
wunderschönen Buffer-Overflow und ein grauenhaftes Interface.

Michael Reinelt schrieb:
> Und jetzt gehen wir mal weg von der grauen Theorie ins sehr
> farbenprächtige, aber leider auch harte und unfaire real life: dort kann
> man sich die Sprache (C oder C++) und den Compiler nicht immer
> aussuchen.
Ja leider. Aber versuchen kann man's ja mal. Für viele 
Embedded-Plattformen (AVR, ARM, MIPS, MSP430, ...) gibt es mittlerweile 
ja auch C++ Compiler - mindestens mal für alles, für das es einen GCC 
oder Clang gibt. Man sollte auch nicht vergessen dass C++ zu 99% 
abwärtskompatibel ist - man kann bestehende C-Projekte meist fast 
unverändert in einen C++ Compiler stecken und seine C++ Extras dazubauen

von P. M. (mikro23)


Lesenswert?

Da hätte ich auch mal eine Frage an den Herrn Dr. Sommer.
Das mit static const... leuchtet mir schon ein.
Wie vermeide ich aber in folgendem Beispiel die #defines?
1
#define  ENDE_FLAG  0x08
2
...
3
#define  ENDE       (GPIO0 & ENDE_FLAG)
4
...
5
if (ENDE) tuwas

Wenn ich eine Funktion (mit oder ohne inline) verwende, müßte ich 
schreiben:
1
if (ENDE()) ...

Geht das in C auch ohne die Klammern hinter ENDE?

von Dr. Sommer (Gast)


Lesenswert?

Peter M. schrieb:
> Geht das in C auch ohne die Klammern hinter ENDE?
In C nicht dass ich wüsste. In C++ könnte man sich einen 
Konvertierungsoperator schreiben:
1
static const ENDE_FLAG = 0x08;
2
3
class {
4
  public:
5
    inline operator bool () {
6
      return GPIO0 & ENDE_FLAG;
7
    }
8
} ENDE;
9
10
int main () {
11
  if (ENDE) {
12
   ...
13
  }
14
}
Allerdings sind die Klammern beim ENDE() jetzt auch nicht so 
dramatisch...

von P. M. (mikro23)


Lesenswert?

Danke. In C++ ist das schon eleganter.

Nein. So dramatisch sind die Klammern nicht.
Es sieht halt ohne besser aus. ;)

Dann werde ich mich wohl bei Gelegenheit mal wieder mit C++ 
beschäftigen. Die Syntax unterscheidet sich da doch schon etwas. Da GCC, 
wie ich gelesen habe, auch C-Programme übersetzt, könnte es allerdings 
ganz hilfreich sein, einiges von C++ mitzubenutzen.

Btw: fehlt da hinter static const ... nicht ein uint8_t?

von Dr. Sommer (Gast)


Lesenswert?

Peter M. schrieb:
> Dann werde ich mich wohl bei Gelegenheit mal wieder mit C++
> beschäftigen. Die Syntax unterscheidet sich da doch schon etwas. Da GCC,
> wie ich gelesen habe, auch C-Programme übersetzt, könnte es allerdings
> ganz hilfreich sein, einiges von C++ mitzubenutzen.
Ja, und wie gesagt kannst du C-Programme auch einfach als C++ 
übersetzen. Gibt nur einige wenige Stellen die du evtl. etwas anpassen 
musst (sagt dir der Compiler dann).
> Btw: fehlt da hinter static const ... nicht ein uint8_t?
Öhm - ja.

von Rainer V. (rudi994)


Lesenswert?

Mittels #define kann man auch fremdsprachigen Sourcecode in den 
C-Compiler reinschieben: 
http://www2.informatik.uni-halle.de/lehre/c/c_prepas.html

von MCUA (Gast)


Lesenswert?

>Mittels #define kann man auch fremdsprachigen Sourcecode in den
>C-Compiler reinschieben:
Bloss, dass bei VB der Variable-typ, nicht wie bei C, hinten (mit as 
...) angehängt wird.

von Kein Name (Gast)


Lesenswert?

> Mittels #define kann man auch fremdsprachigen Sourcecode
> in den C-Compiler reinschieben:

Stimmt, aber das Beispiel taugt nichts. http://www.ioccc.org

von Dr. Sommer (Gast)


Lesenswert?

Rainer V. schrieb:
> Mittels #define kann man auch fremdsprachigen Sourcecode in den
> C-Compiler reinschieben:
Ja super, aber mehr als eine Provokation ist das nicht...

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.