Hallo Leute, man liest ja oft, dass für Mikrocontroller C++ nur bedingt geeignet ist, da sehr viele Ressourcen in Anspruch genommen werden. Im Prinzip bringt aber C++ doch nur Komplexität in den Maschinencode, sobald irgendwelche dynamischen Sprachfeatures verwendet werden! Meine Frage nun: Auf welche Sprachfeatures sollte ich lieber verzichten, welche kann ich ruhigen Gewissens einsetzen? Eine kleine Liste, zu der ich mir Feedback wünsche: Klassen und Vererbung/Polymorphie: Stell ich mir jetzt überhaupt nicht schädlich vor. Sind ja im Prinzip nur Structs mit Funktionen. Templates: Ich denke, dass man Templates schon benutzen kann. Der Compiler baut ja die Klassen/Funktionen nur zusammen, wenn man das Template mit dem entsprechenden Typ auch benutzt. Exceptions: Hmm, schwer. Ich weiß nicht genau, wie sie intern funktionieren. Kann mir vorstellen, dass durch diese Abbruchsprungpunkte eine Menge Maschinencode generiert wird!? Run Time Type Information (RTTI): Hört sich auch nicht so light-weight an. Habe ich bisher kaum genutzt und es tut glaube ich im Mikrocontrollerbereich auch nicht sooo weh darauf zu verzichten. Operator Überladung: Ich glaube, das läuft alles im Compiler ab und dient nur der Programmier-Ergonomie. Da sollte nix besonders passieren, oder? Bleiben jetzt noch Performance oder Ressourcen Nachteile von C++ gegenüber C? Danke! Gruß, Emil
Also die meisten C++ Compiler die ich kenne legen eine Sprungtabelle für die Verwaltung der einzelnen Objekte an was mehr RAM erfordert. Ansonsten kommt es sicherlich darauf an was erreicht werden soll. Auf einem 8bitter macht C++ sicherlich wenig Sinn, wenn dagegen genügend RAM zur Verfügung steht sollte man schon alles verwenden was die Sprache hergibt. Dafür ist es ja gemacht.
Keins der von dir genannten Features (und auch keins der nicht genannten) benötigt im C++ (ernsthaft) mehr Resourcen als in C, wenn du wirklich GENAU die selbe Funktionalität (!!!) implementierst. Dazu ist die Gattung "Mikrocontroller" weit gefasst. Auf einem Tiny mit 128 byte Ram ist manches schlicht nicht möglich, auf einem ARM mit 64kB Ram oder mehr nimmt man volles C++, ohne überhaupt darüber nachzudenken. In diesem Sinne... Oliver
Emil J. schrieb: > man liest ja oft, dass für Mikrocontroller C++ nur bedingt geeignet ist, > da sehr viele Ressourcen in Anspruch genommen werden. µC gibt es von .. bis. Daher: Das kann man so pauschal nicht sagen. Beschränken wir uns mal auf die kleinen, die mit wenig SRAM > Im Prinzip bringt aber C++ doch nur Komplexität in den Maschinencode, > sobald irgendwelche dynamischen Sprachfeatures verwendet werden! Damit hast du dann auch schon dein Hauptkriterium: Alles was mit dynamischer Datenstruktur zu tun hat. Leider beinhaltet das auch die std::string Klasse bzw. überhaupt die Container-Klassen. > Eine kleine Liste, zu der ich mir Feedback wünsche: > Klassen und Vererbung/Polymorphie: > Stell ich mir jetzt überhaupt nicht schädlich vor. Sind ja im Prinzip > nur Structs mit Funktionen. Seh ich kein Problem. Virtuelle Funktionen brauchen zwar ein bischen was (die VTable), ist aber normalerweise nicht so schlimm und: die Alternative "Typ Member samt Cases" braucht auch Resourcen. > Templates: > Ich denke, dass man Templates schon benutzen kann. Der Compiler baut ja > die Klassen/Funktionen nur zusammen, wenn man das Template mit dem > entsprechenden Typ auch benutzt. Kein Problem > Exceptions: > Hmm, schwer. Ich weiß nicht genau, wie sie intern funktionieren. Da Exceptions funktionsübergreifend funktionieren kannst du deinen A... drauf verwetten, dass da dynamische Speicherallokierung im Spiel ist. > Run Time Type Information (RTTI): > Hört sich auch nicht so light-weight an. Habe ich bisher kaum genutzt > und es tut glaube ich im Mikrocontrollerbereich auch nicht sooo weh > darauf zu verzichten. RTTI ist zwar manchmal ganz nett, da es aber auch lange Zeit in C++ ohne ging, braucht man die nicht so oft. Mit Polymorphie und virtuellen Funktionen kommt man schon sehr weit. > Ich glaube, das läuft alles im Compiler ab und dient nur der > Programmier-Ergonomie. Da sollte nix besonders passieren, oder? Jep. > Bleiben jetzt noch Performance oder Ressourcen Nachteile von C++ > gegenüber C? Ist auf µC meistens nicht so sehr das Thema, aber die Stream-Library hat normalerweise stark aufgetragen. Braucht man aber bei typischen Steuerungsaufgaben eher selten :-)
Ich habe alles dynamische mit new/delete weggelassen. Dynamischer Speicher wollte ich in Interrupts nun doch nicht benutzen. Bei C hätte ich dann wohl auch malloc gespart. Den Rest von C++ habe ich benutzt.
Danke für eure Beiträge. Hat mir ein wenig die Angst genommen beim nächsten Projekt auf C setzen zu müssen :D Emil
> Templates: > Ich denke, dass man Templates schon benutzen kann. Der Compiler baut ja > die Klassen/Funktionen nur zusammen, wenn man das Template mit dem > entsprechenden Typ auch benutzt. schon richtig. aber man kann mit einer unbedachten zeile code eine menge platz mehr benötigen. also vorsicht. Wie Karl Heinz schon geschrieben hat: verzichte wenn möglich auf die iostreams. das mag zwar bequem zur ausgabe von debugging-code und ähnlichem sein, kostet dich aber ne riesenmenge an platz.
Des Weiteren gibt's Sprachfeatures, die praktisch sind und gar nichts kosten. Wie z.B. namespaces. Und ehrlich: Lieber brauche ich ein paar Bytes mehr und dafür ist der Code dann deutlich wartbarer.
Ich hatte mal ein paar Versuche auf diversen atmegas mit c++ gemacht. Das geht schon alles, aber da man sich wirklich alles selbst basteln muss(new, stream-klassen, ...) war es ein bisschen witzlos. Wer das mehr aus akademischem interesse macht haette sicher spass daran, aber wenn man einfach nur was steuern will ists eher nichts. Was an wirklich anwendbarem (auf uCs mit 1000 Byte Ram) bleibt sind namespaces, consts und ganz selten mal ein template.
Oliver schrieb: > Keins der von dir genannten Features (und auch keins der nicht > genannten) benötigt im C++ (ernsthaft) mehr Resourcen als in C, wenn du > wirklich GENAU die selbe Funktionalität (!!!) implementierst. Das stimmt einfach nicht. Eine sinnvolle Definition von "GENAU die selbe Funktionalität" ist nämlich, daß sich die vom Compiler erzeugten Programme nicht anhand ihrer Seiteneffekte unterscheiden, d.h. z.B. wann/wie volatile Zugriffe (SFRs etc.) geschehen, wie auf globale Variablen zugegriffen wird, etc. Wenn ich zum Beispiel Exceptions in C++ einerseits und setjmp/longjmp andererseits vergleiche, ist zweiteres wesentlich effektiver. Schaut man sich zum Beispiel an, wie groß der unwind-Code einer für AVR generierten libstdc++ ist, landet man bei ca. 30KiB. Anderes Beispiel sind VTables. In C++ liegen diese im knapp bemessenen RAM. In C ist es zwar etwas mehr Getippse, aber man kann LUTs ins Flash legen oder die paar Fälle codieren. Nächstes Beispiel globale Konstanten. Dazu folgenden Beispiel: Wir wollen eine effiziente Arithmetik und verwenden dazu Fixed-Point Arithmetik, weil unser µC keine Hardware-Unterstützung für float mitbringt. Kalibrier-Werte und Lookup-Tabellen legen wird wegen des knappen RAMs ins Flash. C: Wir verwenden den Fixed-Point Support von ISO/IEC TR 18037. Konstanten im Flash sind kein Problem. C++: Weil wir "sauber" programmieren wollen, schreiben wir die Fixed-Point Arithmetik als Klasse(n) mit überladenen Operatoren. Ziemlich viel Handarbeit, weil C++ keine Obermenge von C ist. Selbst wenn wir alle Funktionen zusammen haben und uns die Finger an (Inline)-Assembler wund geschrieben haben, ist die Performance immer noch schlechter als es der C-Compiler macht. And jeder Stelle, wo Literale wie 3.14 verwendet werden, müssen wir hollisch aufpassen, daß wir uns nicht über die Hintertür doch wieder float-Arithmetik einhandeln -- etwa zur Konvertierung oder Multiplikationen/Divisionen zur Anpassung des Dezimalpunks/Nachkommastellen. Dann die böse C++-Überraschung: Für die Konstanten-Tabellen erzeugt der C++-Compiler ad-doc Konstruktoren und geht davon aus, daß die Tabellem im RAM stehen, und das selbst dann, wenn die Konstanten zu Compilezeit bekannt sind und die Klasse keine VTables braucht. Um das zu umgehen, schreiben wir hässliche Makros, die die Kapselung unserer Fixed-Point Implementierung konterkarieren und fangen mit wüsten, geschachtelten Makros an, die es erlauben, die interne Darstellung der Zahlen zu Compilerzeit zu [de]serialisieren.
Ich kann mich hier nur der Meinung von Johann L. anschließen. All die Sprachfeatures von C++ würde ich niemals auf einem kleinen Controller haben wollen. Und da zähle ich auch die Cortex M0-M4 dazu. Einen echten Vorteil kann ich nicht erkennen. Die Standard C++ Libs sind ohne dynamische Speicherverwaltung nicht möglich. Setzt man sie trotzdem ein, hat man überhaupt keinen Überblick über den Controller und dessen beschränkte Resourcen mehr. Ich tu mich mit den printf-Funktionen aus der newlib schon schwer und nehme dafür lieber was angepasstes kleines. Ich habe auch bei der PC-Programmierung nie verstanden was die C++ Std Lib für Vorteile bringen soll. Solche elementaren Sachen wie Strings, Container und Listen hat man irgendwann einmal für seine Bedürfnisse implementiert und kann sie immer wieder verwenden. Ich weiß gar nicht wie oft ich in den 21 Jahren, seit dem ich mit C++ auf dem PC unterwegs bin, den Compiler wechseln musste. Die Std C++ Lib habe ich noch nie gebraucht oder vermisst. Und mir damit viel Ärger erspart. Die eigenen String- und Containerklassen haben diese Zeit überlebt. Vor 30 Jahren, als ich mit Assembler den Z80 programmiert habe, da kannte ich noch jedes Bit persönlich. Man hatte den Überblick über alles. Dieses gute Gefühl kann man heute auch noch auf den Controllern haben solange sie ohne Betriebssystem sind. Sobald aber Bibliotheken ins Spiel kommen von denen kaum der Stackbedarf bekannt ist, bzw. die dynamischen Speicher nach eigenem Belieben anfordern, hat man dieses Gefühl nicht mehr. Man kann ohne Frage C++ auch gut auf einem kleinen Controller einsetzen. Aber mehr in der Form C mit Klassen. Das macht den Code häufig wesentlich besser lesbar. Wenn die Controller größer werden und ein richtiges Betriebssystem drunter liegt, sieht die Sache anders aus. Da kann man aus dem vollen Schöpfen wenn man unbedingt will. Da benutzt man das alles aber auch in der Art und Weise für das es mal erfunden wurde. Und ob ich nun von 98% oder 99% des Codes der da läuft keine Ahnung mehr habe spielt am Ende auch keine Rolle mehr.
Johann L. schrieb: > Schaut > man sich zum Beispiel an, wie groß der unwind-Code einer für AVR > generierten libstdc++ ist, landet man bei ca. 30KiB. Alles richtig. Allerdings war die Frage allgemein auf Mikrocontroller gestellt, und da ist die zugegebenermassen sehr ungünstige AVR-GCC-C++-Implementation wohl nicht zu verallgemeinern. Oliver
Arduino nutzt C++. Es gibt allerdings auch C Compiler welche zusätzliche C++ Features bereitstellen wie z.B. function overloading. Was aber auch zu beachten ist, C hat einen anderen Namespace als C++. Z.B. teilen enums und structs in C++ denselben Namespace als Variablen, in C haben sie einen eigenen Namespace und die Zuweisung von Variablen ist in C++ heikler, in dem Sinne daß eine Typenkorrektheit erzwungen wird. Da gehen dann einfache Sachen nicht mehr, wie prüfen ob eine FP Zahl negativ ist und zwar als Integer, nicht als FP. Function overloading ist ganz nett, ansonsten nein danke. Aber wie bereits gesagt wurde, ist genügend Ram vorhanden, dann ist C++ auch bedenkenlos aber mit Bedacht einsetzbar.
Ich dachte an den Einsatz von C++ auf einem STM32. Sprachfeatures, die ich schon sehr gerne benutzen würde, sind halt Funktionsüberladung (vielleicht Operatorüberladung), Templates, Exceptions und natürlich Klassen und Polymorphie. Für die Rechenintensive Anwendung möchte ich einen STM32F4xx verwenden, der hat eine FPU. Gruß, Emil
Mach es einfach... Die C++-Sprachfeatures bringen dich da nicht um. Bei der Verwendung der std::xxx libs musst du halt aufpassen, da solltest du das verfügbare Ram im Auge behalten. Oliver
Ich programmiere meine AVR-Projekte inzwischen alle nur noch in C++, weil man mit Klassen meines Erachtens deutlich besser kapseln kann als in mit C-Modulen. Gerade Vererbung, Überladung etc. ist sehr elegant und kostet nicht mehr, als man für die entsprechende C-Implementierung auch gebraucht hätte. Da ich auf laufzeit-komplexe Dinge wie Streams, Exceptions usw. verzichte, ist der Ressourcen-Bedarf zwischen C und C++ ziemlich identisch. Man ist ja nicht gezwungen, alle C++ Features ausschöpfen zu wollen, man kann sich ja das sinnvollste aussuchen, und dann ist meines Erachtens C++ auch auf einem 8-Bitter absolut vorteilhaft.
Hi! Wenn man sich jederzeit bewusst macht, was die Auswirkungen eines Sprach-Features auf den Maschinencode, Flash- und RAM-Verbrauch haben, ist C++ eine saubere Sache auch für einen Mikrocontroller mit wenig Flash und RAM. Gerade für komplexe Projekte bietet C++ mehr, um den Code sauber zu strukturieren und zu dokumentieren. Vererbung kostet z.B. keine Ressourcen zur Laufzeit. Schau doch mal hier vorbei: http://roboterclubaachen.github.com/xpcc/ http://roboterclubaachen.github.com/xpcc/api/ Dort wird C++ für Mikrocontroller (AVR, ARM Cortex-M0 bis Cortex-M4, ARM 7, AVR32, ...) benutzt. Bei dem Beispiel http://roboterclubaachen.github.com/xpcc/api/group__gpio.html wird auch erläutert, wie das dann in Maschinencode aussieht. Bewährt haben sich auf jeden Fall statische Methoden und Templates. Der Overhead durch vtables ist verschmerzbar, wenn man dadurch saubere, kompatible Interfaces hinbekommt. LG Dave
Dave schrieb: > Gerade für komplexe Projekte bietet C++ mehr, um den Code sauber zu > strukturieren und zu dokumentieren. schon merkwürdig das der ganze linux Kernel nur in C geschrieben ist, auch die leute dort noch den überblick behalten. Man kann in C genauso sauber struktieren wie in C++. Das ist nur eine gewöhnungsfrage.
Dave schrieb: > Schau doch mal hier vorbei: > > http://roboterclubaachen.github.com/xpcc/ > http://roboterclubaachen.github.com/xpcc/api/ Das ist für mich ein klasse Negativbeispiel. Viel Aufwand für eine erlesen Auswahl an MCs. Und in meinen Augen unübersichtlich. Sowas würde ich mir nicht auf den Controller holen. Mag sein dass der Compiler daraus ordenlichen Code generiert. Das ist wieder wie mit jeder Lib. Wenn man alle Möglichkeiten der Perepherie bedenkt kriegt man einen riesen Klotz ans Bein gebunden. Wenn nur der kleinste gemeinsame Nenner drin ist, fehlt es überall und man fängt an dazu zu bauen. Wenn es dann ein neues Release der Lib gibt, geht's wieder von vorne los. Das ist aber unabhängig von C++. Irgendwie wiederholt sich der Schwachsinn, der in der PC-Programmierung zu beobachten ist, auf den Controllern. Das Ausnutzen der ganzen Möglichkeiten von C++ führt zu mehr unverständlichen Code als weniger. Klar ist es super einfach und verständlich ein "Led.Toggle()" zu benutzen. Wenn ich aber 5 Header- und Quellcode Dateien durchforsten muss um zu verstehen wie "Led" funktioniert, dann stimmt was nicht. Das Ziel der "Kapselug" sollte nicht in einem Versteckspiel enden. Das ist aber nur meine Meinung und andere sind ausdrücklich erlaubt.
PittyJ schrieb: > Ich habe alles dynamische mit new/delete weggelassen. Dynamischer > Speicher wollte ich in Interrupts nun doch nicht benutzen. > Bei C hätte ich dann wohl auch malloc gespart. > > Den Rest von C++ habe ich benutzt. So habe ich es auf einem STM32 auch gehalten. Dynamisch mache ich nix. Ist zwar manchmal ein wenig Speicherplatzverschwendung, aber ist aufgrund der Menge an Speicher überhaupt kein Problem
Peter II schrieb: > schon merkwürdig das der ganze linux Kernel nur in C geschrieben ist, > auch die leute dort noch den überblick behalten. Kernels sollte man aus Gründen der Stabilität und Einfachheit eigentlich immer in C (und ja, ohne Assembler geht's auch nicht) schreiben. Bei Libraries gilt wieder: Nur C hat eine standardisierte und portable API. Bei OpenSource ist das bei C++ nicht so ein Thema, aber sobald es ums Einbinden fremder Libraries geht, kann man sich da tüchtig ins Knie schiessen. Generell würde ich für stabile Software von C++ auf uCs ohne Betriebssystem eher absehen, einige 'bequeme' Features wie Exceptions und Allocator können recht tückisch sein und das Debugging schwierig machen. Dasselbe gilt aber auch für masslose Anwendung von C malloc(). Im Endeffekt halt eine Frage ob Hobby oder nötige Industrietauglichkeit. Im 'userspace' und für nicht kritische Tasks (GUI) ist C++ völlig ok, in einem sauberen Kernel wiederum ein no-go. Das generelle Problem bei vielen C++-Programmen ist der oft zu akademische Ansatz, um auf Teufel-komm-raus objektorientierten Code zu schreiben. Oft lernen die Studenten schon gar kein C, geschweige denn Assembler mehr. Da geht das Keep-it-simple-Prinzip dann teils total verloren und artet nur noch in Coding-Onanie aus. Was das ganze auf den ersten Blick bei C++ einfacher macht, verleitet dann zu miesem Code-Design. Die Nachteile von C++ überwiegen bei uC-Projekten (Portabilität, Platzbedarf) meiner Meinung nach. Wenn ich den Platz habe, haue ich lieber einen Python-Interpreter mit drauf und habe gleich eine vernünftige OO-Runtime-Umgebung mit Scripting.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.