webentwicklung-frage-antwort-db.com.de

Gibt es einen Grund, C anstelle von C ++ für die Embedded-Entwicklung zu verwenden?

Frage

Ich habe zwei Compiler auf meiner Hardware C++ und C89

Ich denke über die Verwendung von C++ mit Klassen, aber ohne Polymorphismus (um vtables zu vermeiden). Die Hauptgründe, warum ich C++ verwenden möchte, sind:

  • Ich bevorzuge die Verwendung von Inline-Funktionen anstelle von Makrodefinitionen.
  • Ich möchte Namespaces verwenden, da Präfixe den Code überladen.
  • Ich sehe C++ ein bisschen sicherer, hauptsächlich aufgrund von Vorlagen und ausführlichem Casting.
  • Ich mag überladene Funktionen und Konstruktoren (die für das automatische Casting verwendet werden).

Sehen Sie einen Grund, bei der Entwicklung von sehr begrenzter Hardware (4 KB RAM) bei C89 zu bleiben?

Fazit

Vielen Dank für Ihre Antworten, sie waren wirklich hilfreich!

Ich habe das Thema durchdacht und werde mich hauptsächlich an C halten, weil:

  1. Es ist einfacher, tatsächlichen Code in C vorherzusagen, und dies ist wirklich wichtig, wenn Sie nur 4 KB RAM haben.
  2. Mein Team besteht hauptsächlich aus C-Entwicklern, daher werden erweiterte C++ - Funktionen nicht häufig verwendet.
  3. Ich habe in meinem C-Compiler (C89) eine Möglichkeit gefunden, Funktionen inline auszuführen.

Es ist schwierig, eine Antwort zu akzeptieren, da Sie so viele gute Antworten gegeben haben. Leider kann ich kein Wiki erstellen und akzeptiere es nicht. Daher werde ich eine Antwort auswählen, die mich am meisten zum Nachdenken gebracht hat.

77
Piotr Czapla

Zwei Gründe für die Verwendung von C über C++:

  1. Für viele Embedded-Prozessoren gibt es entweder keinen C++ - Compiler, oder Sie müssen dafür extra bezahlen.
  2. Ich habe die Erfahrung gemacht, dass ein beträchtlicher Teil der Entwickler von Embedded-Software wenig oder gar keine Erfahrung mit C++ hat - entweder aufgrund von (1) oder weil C++ in der Regel nicht in elektronischen Ingenieurdiplomen unterrichtet wird - und es daher besser ist, sich daran zu halten was sie wissen.

Auch die ursprüngliche Frage und eine Reihe von Kommentaren erwähnen die 4 Kb von [~ # ~] ram [~ # ~]. Bei einem typischen eingebetteten Prozessor hängt die Größe von RAM) (meistens) nicht von der Codegröße ab, da der Code gespeichert und von Flash ausgeführt wird.

Die Größe des Code-Speicherplatzes muss natürlich beachtet werden, aber da neue, leistungsfähigere Prozessoren auf dem Markt erscheinen, ist dies weniger ein Problem als früher für alle anderen Projekte mit Ausnahme der kostenintensivsten Projekte.

Zur Verwendung einer Teilmenge von C++ für die Verwendung mit eingebetteten Systemen: Es gibt jetzt einen MISRA C++ - Standard, der einen Blick wert sein kann.

EDIT: Siehe auch diese Frage , was zu einer Debatte über C vs C++ für eingebettete Systeme führte.

42
Steve Melnikoff

Für ein sehr ressourcenbeschränktes Ziel, wie 4 KB RAM, würde ich das Wasser mit einigen Proben testen, bevor ich viel Aufwand aufbringe, der nicht sein kann Einfache Portierung in eine reine ANSI C-Implementierung.

Die Embedded C++ - Arbeitsgruppe hat eine Standarduntermenge der Sprache und eine Standarduntermenge der Standardbibliothek vorgeschlagen, die dazu passen. Ich habe den Überblick verloren, als das C User's Journal leider verstarb. Es sieht so aus, als gäbe es einen Artikel bei Wikipedia , und der Ausschuss existiert noch.

In einer eingebetteten Umgebung müssen Sie bei der Speicherzuweisung wirklich vorsichtig sein. Um diese Sorgfalt durchzusetzen, müssen Sie möglicherweise das globale operator new() und seine Freunde mit etwas definieren, das nicht einmal verknüpft werden kann, damit Sie wissen, dass es nicht verwendet wird. Placement new hingegen ist wahrscheinlich Ihr Freund, wenn es mit einem stabilen, threadsicheren und latenzgarantierten Zuweisungsschema sinnvoll verwendet wird.

Inline-Funktionen verursachen nicht viele Probleme, es sei denn, sie sind groß genug, um überhaupt echte Funktionen zu sein. Natürlich hatten die Makros, die sie ersetzten, das gleiche Problem.

Auch Vorlagen verursachen möglicherweise keine Probleme, es sei denn, ihre Instanziierung wird amok ausgeführt. Überprüfen Sie für jede Vorlage, die Sie verwenden, Ihren generierten Code (die Verknüpfungszuordnung verfügt möglicherweise über ausreichende Hinweise), um sicherzustellen, dass nur die von Ihnen beabsichtigten Instanziierungen ausgeführt wurden.

Ein weiteres Problem, das auftreten kann, ist die Kompatibilität mit Ihrem Debugger. Es ist nicht ungewöhnlich, dass ein ansonsten verwendbarer Hardware-Debugger die Interaktion mit dem ursprünglichen Quellcode nur sehr eingeschränkt unterstützt. Wenn Sie effektiv in Assembly debuggen müssen, kann die interessante Namensverknüpfung von C++ die Aufgabe zusätzlich verwirren.

RTTI, dynamische Casts, Mehrfachvererbung, starker Polymorphismus und Ausnahmen sind mit gewissen Laufzeitkosten verbunden. Einige dieser Funktionen kosten das gesamte Programm, andere erhöhen lediglich das Gewicht der Klassen, die sie benötigen. Erkennen Sie den Unterschied und wählen Sie erweiterte Funktionen mit Bedacht aus, wobei Sie mindestens eine vorläufige Kosten-Nutzen-Analyse kennen.

In einer kleinen eingebetteten Umgebung werden Sie entweder direkt mit einem Echtzeit-Kernel verbunden oder direkt auf der Hardware ausgeführt. In beiden Fällen müssen Sie sicherstellen, dass Ihr Laufzeit-Startcode C++ -spezifische Startaufgaben korrekt verarbeitet. Dies kann so einfach sein, wie sicherzustellen, dass die richtigen Linker-Optionen verwendet werden. Da es jedoch üblich ist, die Quelle direkt über den Einstiegspunkt zum Zurücksetzen beim Einschalten zu steuern, müssen Sie dies möglicherweise überprüfen, um sicherzustellen, dass alles funktioniert. Auf einer ColdFire-Plattform, an der ich gearbeitet habe, wurden die Entwicklertools mit einem CRT0.S-Modul ausgeliefert, in dem die C++ - Initialisierer vorhanden, aber auskommentiert waren. Wenn ich es direkt aus der Schachtel verwendet hätte, wären mir globale Objekte in den Sinn gekommen, deren Konstruktoren noch nie gelaufen wären.

In einer eingebetteten Umgebung müssen Hardwaregeräte häufig initialisiert werden, bevor sie verwendet werden können. Wenn kein Betriebssystem und kein Bootloader vorhanden sind, ist dies Ihr Code. Sie müssen sich daran erinnern, dass Konstruktoren für globale Objekte ausgeführt werden , bevor main() aufgerufen wird, sodass Sie Ihre lokale CRT0 ändern müssen. S (oder dessen Äquivalent), um diese Hardware-Initialisierung durchzuführen , bevor die globalen Konstruktoren selbst aufgerufen werden. Offensichtlich ist der Anfang von main() viel zu spät.

64
RBerteig

Nein. Alle C++ - Sprachfunktionen, die Probleme verursachen können (Laufzeitpolymorphismus, RTTI usw.), können bei der Embedded-Entwicklung vermieden werden. Es gibt eine Community von Embedded C++ - Entwicklern (ich erinnere mich, dass ich Spalten von Embedded-Entwicklern gelesen habe, die C++ im alten C/C++ - Benutzerjournal verwendet haben), und ich kann mir nicht vorstellen, dass sie sehr lautstark wären, wenn die Auswahl so schlecht wäre.

25
Harper Shelby

Der Technical Report on C++ Performance ist ein guter Leitfaden für diese Art von Dingen. Beachten Sie, dass es einen Abschnitt zum Thema eingebettete Programmierung gibt!

Auch ++ über die Erwähnung von Embedded C++ in den Antworten. Der Standard entspricht nicht zu 100% meinem Geschmack, ist aber eine gute Referenz, wenn Sie entscheiden, welche Teile von C++ Sie löschen möchten.

Bei der Programmierung für kleine Plattformen haben wir Ausnahmen und RTTI deaktiviert, die virtuelle Vererbung vermieden und der Anzahl der virtuellen Funktionen, die wir haben, große Aufmerksamkeit geschenkt.

Ihr Freund ist jedoch die Linker-Map: Überprüfen Sie sie regelmäßig, und Sie werden schnell feststellen, woher der Code stammt und wie schnell sich der statische Speicher aufbläht.

Danach gelten die standardmäßigen Überlegungen zur dynamischen Speichernutzung: In einer Umgebung, die so eingeschränkt ist wie die von Ihnen erwähnte, möchten Sie möglicherweise überhaupt keine dynamischen Zuordnungen verwenden. Manchmal können Sie mit Speicherpools für kleine dynamische Zuweisungen oder "rahmenbasierte" Zuweisungen davonkommen, bei denen Sie einen Block vorbelegen und das Ganze später wegwerfen.

20
leander

Ich empfehle die Verwendung des C++ - Compilers, beschränke jedoch die Verwendung von C++ - spezifischen Funktionen. Sie können wie C in C++ programmieren (die C-Laufzeit ist in C++ enthalten, obwohl Sie in den meisten eingebetteten Anwendungen ohnehin nicht die Standardbibliothek verwenden).

Sie können einfach C++ - Klassen usw. verwenden

  • Beschränken Sie Ihre Nutzung virtueller Funktionen (wie Sie gesagt haben)
  • Beschränken Sie die Verwendung von Vorlagen
  • Bei einer eingebetteten Plattform möchten Sie den Operator new überschreiben und/oder die Platzierung new für die Speicherzuweisung verwenden.
16
arke

Als Firmware-/Embedded-System-Ingenieur kann ich Ihnen einige Gründe nennen, warum C immer noch die erste Wahl gegenüber C++ ist, und ja, ich spreche beide fließend.

1) Einige Ziele, auf denen wir entwickeln, haben 64kB RAM für Code und Daten, daher müssen Sie sicherstellen, dass alle Bytes gezählt werden, und ja, ich habe mich mit der Codeoptimierung befasst, um 4 Bytes zu sparen das hat mich 2 stunden gekostet und das ist im jahr 2008.

2) Aus Gründen der Größenbeschränkung wird jede C-Bibliotheksfunktion überprüft, bevor wir sie in den endgültigen Code aufnehmen. Daher bevorzugen wir die Verwendung von divide (kein Hardwareteiler, daher wird eine große Bibliothek benötigt) und malloc (weil wir keinen Heap haben) wird der gesamte Speicher aus dem Datenpuffer in einem 512-Byte-Block zugewiesen und muss einem Code-Review unterzogen werden. Denken Sie daran, dass jede Bibliotheksfunktion, die Sie verwenden, zählt.

3) Schon mal was von dem Begriff Overlay gehört? Sie haben so wenig Code-Platz, dass Sie manchmal Dinge mit einem anderen Satz von Code austauschen müssen. Wenn Sie eine Bibliotheksfunktion aufrufen, muss die Bibliotheksfunktion resident sein. Wenn Sie es nur in einer Überlagerungsfunktion verwenden, verschwenden Sie viel Platz, indem Sie zu viele objektorientierte Methoden verwenden. Nehmen Sie also keine C-Bibliotheksfunktion an, geschweige denn C++, um akzeptiert zu werden.

4) Casting und gleichmäßiges Packen (wenn die nicht ausgerichtete Datenstruktur die Wortgrenze überschreitet) sind aufgrund des eingeschränkten Hardware-Designs (d. H. Einer ECC-Engine, die auf eine bestimmte Weise verdrahtet ist) oder zur Behebung eines Hardware-Fehlers erforderlich. Sie können nicht zu viel implizit annehmen, warum sollte das Objekt es also zu sehr ausrichten?

5) Worst-Case-Szenario: Durch das Eliminieren einiger objektorientierter Methoden wird die Entwicklung gezwungen zu überlegen, bevor Ressourcen verwendet werden, die explodieren können (dh 512 Byte auf einem Stapel anstatt aus einem Datenpuffer), und einige der potenziellen Worst-Case-Szenarien, die explodieren werden nicht auf den gesamten Codepfad getestet oder eliminiert.

6) Wir verwenden viel Abstraktion, um Hardware von Software fernzuhalten und Code so portabel wie möglich und simulationsfreundlich zu machen. Der Hardwarezugriff muss in ein Makro oder eine Inline-Funktion eingeschlossen werden, die bedingt zwischen verschiedenen Plattformen kompiliert werden. Der Datentyp muss als Byte-Größe und nicht als zielspezifisch umgewandelt werden. Eine direkte Zeigerverwendung ist nicht zulässig (da einige Plattformen davon ausgehen, dass die speicherzugeordnete E/A die ist wie Datenspeicher) usw.

Ich kann an mehr denken, aber Sie erhalten die Idee. Wir Firmware-Leute haben objektorientiertes Training, aber die Aufgabe eines eingebetteten Systems kann so hardwareorientiert und niedrig sein, dass es von Natur aus nicht hochgradig oder abstrahierbar ist.

Übrigens, jeder Firmware-Job, bei dem ich gearbeitet habe, verwendet die Quellcodeverwaltung. Ich weiß nicht, woher Sie diese Idee haben.

-Einige Firmware-Typen von SanDisk.

14
Shing Wong

Meine persönliche Präferenz ist C, weil:

  • Ich weiß, was jede Codezeile tut (und kostet)
  • Ich kenne C++ nicht gut genug, um zu wissen, was jede Codezeile tut (und kostet)

Warum sagen die Leute das? Sie nicht wissen, was jede Zeile von C tut, es sei denn, Sie überprüfen die ASM-Ausgabe. Gleiches gilt für C++.

Zum Beispiel, was asm erzeugt diese unschuldige Aussage:

a[i] = b[j] * c[k];

Es sieht ziemlich unschuldig aus, aber ein GCC-basierter Compiler erzeugt diesen Code für ein 8-Bit-Mikro

CLRF 0x1f, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1f, F, ACCESS
MOVWF 0x1e, ACCESS
MOVLW 0xf9
MOVF 0xfdb, W, ACCESS
ADDWF 0x1e, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfa
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1f, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x1c
NOP
MOVFF 0xfef, 0x1d
NOP
MOVLW 0x1
CLRF 0x1b, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1b, F, ACCESS
MOVWF 0x1a, ACCESS
MOVLW 0xfb
MOVF 0xfdb, W, ACCESS
ADDWF 0x1a, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfc
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1b, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x18
NOP
MOVFF 0xfef, 0x19
NOP
MOVFF 0x18, 0x8
NOP
MOVFF 0x19, 0x9
NOP
MOVFF 0x1c, 0xd
NOP
MOVFF 0x1d, 0xe
NOP
CALL 0x2142, 0
NOP
MOVFF 0x6, 0x16
NOP
MOVFF 0x7, 0x17
NOP
CLRF 0x15, ACCESS
RLCF 0xfdf, W, ACCESS
ANDLW 0xfe
RLCF 0x15, F, ACCESS
MOVWF 0x14, ACCESS
MOVLW 0xfd
MOVF 0xfdb, W, ACCESS
ADDWF 0x14, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfe
MOVF 0xfdb, W, ACCESS
ADDWFC 0x15, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0x16, 0xfee
NOP
MOVFF 0x17, 0xfed
NOP

Die Anzahl der produzierten Anweisungen hängt massiv ab von:

  • Die Größen von a, b und c.
  • gibt an, ob diese Zeiger auf dem Stapel gespeichert oder global sind
  • ob i, j und k auf dem Stack sind oder global

Dies gilt insbesondere in der winzigen Embedded-Welt, in der Prozessoren nicht für C eingerichtet sind. Meine Antwort wäre also, dass C und C++ genauso schlecht sind wie die anderen, es sei denn, Sie untersuchen immer die ASM-Ausgabe. In diesem Fall sind sie sind genauso gut wie die anderen.

Hugo

10
Rocketmagnet

Ich habe gehört, dass einige Leute C für eingebettete Arbeit bevorzugen, da es einfacher ist und daher leichter ist, den tatsächlich generierten Code vorherzusagen.

Ich persönlich würde denken, dass das Schreiben von C++ im C-Stil (unter Verwendung von Vorlagen für die Typensicherheit) Ihnen viele Vorteile bringt, und ich sehe keinen wirklichen Grund, dies nicht zu tun.

8
user21714

Ich sehe keinen Grund, C anstelle von C++ zu verwenden. Was auch immer Sie in C tun können, Sie können es auch in C++ tun. Wenn Sie Overheads von VMT vermeiden möchten, verwenden Sie keine virtuellen Methoden und keinen Polymorphismus.

C++ kann jedoch einige sehr nützliche Redewendungen ohne Zusatzaufwand bereitstellen. Einer meiner Favoriten ist RAII. Der Unterricht ist nicht unbedingt speicher- oder leistungsintensiv ...

7

Ich habe Code für die in ARM7 eingebettete Paltform auf der IAR Workbench geschrieben. Ich empfehle dringend, Vorlagen für die Optimierung der Kompilierungszeit und die Pfadvorhersage zu verwenden. Vermeiden Sie dynamisches Werfen wie Pest. Verwenden Sie Merkmale/Richtlinien zu Ihrem Vorteil, wie in Andrei Alexandrescus Buch Modernes C++ - Design beschrieben.

Ich weiß, es kann schwer zu lernen sein, aber ich bin auch sicher, dass Ihr Produkt von diesem Ansatz profitieren wird.

6
GregC

Für ein System, das auf 4 KB RAM beschränkt ist, würde ich C und nicht C++ verwenden, nur damit Sie sicher sein können, dass Sie alles sehen, was vor sich geht. Die Sache mit C++ ist, dass es sehr einfach ist, viel mehr Ressourcen (sowohl CPU als auch Speicher) zu verwenden, als es aussieht, als würde man einen Blick auf den Code werfen. (Oh, ich erstelle einfach ein anderes BlerfObject, um das zu tun ... whoops! Out of memory!)

Sie können dies, wie bereits erwähnt, in C++ tun (kein RTTI, keine vtables usw. usw.), aber Sie werden so viel Zeit darauf verwenden, sicherzustellen, dass Ihre C++ - Nutzung nicht an Ihnen vorbei geht, wie Sie dies in C tun würden .

5
Michael Kohne

Ein guter Grund und manchmal der einzige Grund ist, dass es für das spezifische eingebettete System noch keinen C++ - Compiler gibt. Dies ist beispielsweise bei Microchip PIC Mikrocontrollern der Fall. Sie sind sehr einfach zu schreiben und haben einen kostenlosen C-Compiler (eigentlich eine leichte Variante von C), aber es ist kein C++ - Compiler in Sicht.

5
shoosh

Der menschliche Verstand befasst sich mit Komplexität, indem er so viel wie möglich bewertet und dann entscheidet, worauf es ankommt, und den Rest verwirft oder abwertet. Dies ist die gesamte Grundlage für das Branding im Marketing und im Wesentlichen für Ikonen.

Um dieser Tendenz entgegenzuwirken, bevorzuge ich C gegenüber C++, weil es Sie dazu zwingt, über Ihren Code nachzudenken und wie er enger mit der Hardware interagiert - unerbittlich nah.

Aus langjähriger Erfahrung bin ich der Überzeugung, dass C Sie dazu zwingt, bessere Lösungen für Probleme zu finden, zum Teil, indem es Ihnen aus dem Weg geht und Sie nicht dazu zwingt, viel Zeit zu verschwenden, um eine Einschränkung zu erfüllen oder herauszufinden, was "unter der Decke" los ist.

In diesem Sinne haben Sprachen mit niedrigem Sprachniveau wie C viel Zeit damit verbracht, sich auf die Hardware zu konzentrieren und gute Datenstruktur-/Algorithmus-Bundles zu erstellen, während Sprachen mit hohem Sprachniveau viel Zeit damit verbringen, sich am Kopf zu kratzen und sich zu fragen, was dort vor sich geht , und warum Sie in Ihrem spezifischen Kontext und Ihrer Umgebung nichts völlig Vernünftiges tun können. Es ist KEINE produktive Zeitnutzung, den Compiler in die Unterwerfung zu zwingen (starkes Tippen ist der schlimmste Straftäter).

Ich passe wahrscheinlich gut in die Programmierform - ich mag Kontrolle. Meiner Meinung nach ist das kein Persönlichkeitsfehler für einen Programmierer. Kontrolle ist das, wofür wir bezahlt werden. Genauer gesagt, FLAWLESSLY Kontrolle. C gibt Ihnen viel mehr Kontrolle als C++.

4
user1899861

Persönlich würde ich sagen, dass Sie mit 4 KB Speicher nicht so viel mehr Laufleistung aus C++ herausholen. Wählen Sie also diejenige aus, die für den Job die beste Kombination aus Compiler und Laufzeit darstellt, da die Sprache wahrscheinlich keine Rolle spielt.

Beachten Sie, dass es auch nicht nur um Sprache geht, da auch die Bibliothek eine Rolle spielt. Häufig haben C-Bibliotheken eine etwas kleinere Mindestgröße, aber ich könnte mir vorstellen, dass eine C++ - Bibliothek, die auf eingebettete Entwicklung abzielt, reduziert wird. Testen Sie sie daher unbedingt.

3

Einige sagen, dass C-Compiler viel effizienteren Code generieren können, weil sie die erweiterten C++ - Funktionen nicht unterstützen müssen und daher aggressiver in ihren Optimierungen sein können.

In diesem Fall können Sie natürlich die beiden spezifischen Compiler testen.

2
Yishai

Sehen Sie einen Grund, bei der Entwicklung von sehr begrenzter Hardware (4 KB RAM) bei C89 zu bleiben?

Persönlich, wenn es um eingebettete Anwendungen geht (Wenn ich eingebettet sage, meine ich heute nicht WinCE, iPhone, etc .. aufgeblähte eingebettete Geräte). Ich meine ressourcenbeschränkte Geräte. Ich bevorzuge C, obwohl ich auch ziemlich viel mit C++ gearbeitet habe.

Zum Beispiel hat das Gerät, von dem Sie sprechen, 4kb RAM, nur aus diesem Grund würde ich C++ nicht in Betracht ziehen. Sicher, Sie können mit C++ möglicherweise etwas Kleines entwerfen und die Verwendung in Ihrer Anwendung einschränken, wie es andere Posts vorgeschlagen haben, aber C++ "könnte" dazu führen, dass Ihre Anwendung möglicherweise kompliziert oder aufgebläht wird.

Wirst du statisch verlinken? Möglicherweise möchten Sie eine Dummy-Anwendung mit c ++ mit c statisch vergleichen. Das könnte dazu führen, dass Sie stattdessen C in Betracht ziehen. Wenn Sie andererseits in der Lage sind, eine C++ - Anwendung innerhalb Ihrer Speicheranforderungen zu erstellen, entscheiden Sie sich dafür.

IMHO, im Allgemeinen möchte ich in eingebetteten Anwendungen alles wissen, was vor sich geht. Wer verwendet Speicher-/Systemressourcen, wie viel und warum? Wann befreien sie sie?

Bei der Entwicklung für ein Ziel mit X-Mengen an Ressourcen, CPU, Speicher usw. versuche ich, diese Ressourcen nicht zu nutzen, da Sie nie wissen, welche zukünftigen Anforderungen sich daraus ergeben, und Sie dem Projekt mehr Code hinzufügen müssen sollte "angeblich" eine einfache kleine Anwendung sein, wird aber am Ende viel größer.

2
Steve Lazaridis

Meine Wahl wird normalerweise von der C-Bibliothek bestimmt, die wir verwenden. Diese wird basierend auf den Anforderungen des Geräts ausgewählt. Also, 9/10 mal .. es endet damit, dass es uclibc oder newlib und C ist. Der Kernel, den wir verwenden, hat auch einen großen Einfluss darauf, oder wenn wir unseren eigenen Kernel schreiben.

Es ist auch eine Wahl der Gemeinsamkeiten. Die meisten guten C-Programmierer haben kein Problem mit C++ (obwohl sich viele über die gesamte Zeit beschweren, in der sie es verwenden).

Bei einem Projekt, an dem wir arbeiten (bei dem es sich um einen Kernel handelt), werden die meisten Aufgaben in C ausgeführt. In C++ wurde jedoch ein kleiner Netzwerkstapel implementiert, da die Implementierung von Netzwerken mit C++ einfacher und unproblematischer war.

Das Endergebnis ist, dass das Gerät entweder funktioniert und die Abnahmetests besteht oder nicht. Wenn Sie foo mit der Sprache z in xx Stack- und yy Heap-Beschränkungen implementieren können, verwenden Sie alles, was Sie produktiver macht.

Meine persönliche Präferenz ist C, weil:

  • Ich weiß, was jede Codezeile tut (und kostet)
  • Ich kenne C++ nicht gut genug, um zu wissen, was jede Codezeile tut (und kostet)

Ja, ich bin mit C++ vertraut, aber ich kenne es nicht so gut wie Standard C.

Nun, wenn Sie das Gegenteil sagen können, verwenden Sie, was Sie wissen :) Wenn es funktioniert, Tests besteht, etc .. Was ist das Problem?

2
Tim Post

C gewinnt bei der Portabilität - weil es in der Sprachspezifikation weniger mehrdeutig ist; Dies bietet eine viel bessere Portabilität und Flexibilität für verschiedene Compiler usw. (weniger Kopfschmerzen).

Wenn Sie die C++ - Funktionen nicht nutzen möchten, um einen Bedarf zu decken, entscheiden Sie sich für C.

2
Oliver

Wie viel ROM/FLASH hast du?

4kB RAM können immer noch bedeuten, dass Hunderte von Kilobyte FLASH für die Speicherung des tatsächlichen Codes und der statischen Daten zur Verfügung stehen. RAM= bei dieser Größe ist in der Regel nur für gedacht Variablen, und wenn Sie mit diesen vorsichtig sind, können Sie ein ziemlich großes Programm in Bezug auf Codezeilen in den Speicher einpassen.

C++ erschwert jedoch das Einfügen von Code und Daten in FLASH aufgrund der Laufzeit-Konstruktionsregeln für Objekte. In C kann eine konstante Struktur einfach in den FLASH-Speicher gestellt und als Hardwarekonstantenobjekt aufgerufen werden. In C++ würde ein konstantes Objekt erfordern, dass der Compiler den Konstruktor zur Kompilierungszeit auswertet, was meiner Meinung nach immer noch über das hinausgeht, was ein C++ - Compiler kann (theoretisch könnten Sie es tun, aber in der Praxis ist es sehr, sehr schwierig). .

In einer Umgebung mit "kleinem RAM" und "großem FLASH" würde ich also jeden Tag mit C arbeiten. Beachten Sie, dass es sich bei C99 um eine gute Zwischenlösung handelt, die die meisten Funktionen von Nice C++ für nicht auf Klassen basierenden Code bietet.

2
jakobengblom2

Der einzige Grund, C IMHO vorzuziehen, wäre, wenn der C++ - Compiler für Ihre Plattform nicht in einem guten Zustand ist (fehlerhaft, schlechte Optimierung usw.).

1

Ich möchte nur sagen, dass es kein System mit "UNLIMITED" -Ressourcen gibt. Alles auf dieser Welt ist begrenzt und JEDE Anwendung sollte die Ressourcennutzung berücksichtigen, unabhängig davon, ob es sich um ASM, C, Java oder JavaScript handelt. Die Dummies, die ein paar MB "nur um sicher zu sein" zuweisen, machen das iPhone 7 , Pixel und andere Geräte extrem luggy. Egal ob du 4kb oder 40 Gb hast.

Aber von einer anderen Seite, um der Verschwendung von Ressourcen entgegenzutreten - ist eine Zeit, die benötigt wird, um diese Ressourcen zu schonen. Wenn es eine Woche länger dauert, eine einfache Sache in C zu schreiben, um ein paar Ticks und ein paar Bytes zu sparen, anstatt C++ zu verwenden, das bereits implementiert, getestet und verteilt wurde. Warum die Mühe? Es ist wie beim Kauf eines USB-Hubs. ja, du kannst es selbst machen, aber wird es besser? zuverlässiger? billiger, wenn Sie Ihre Zeit zählen?

Nur ein Nebengedanke - auch die Leistung Ihrer Steckdose ist nicht unbegrenzt. Versuchen Sie zu erforschen, woher es kommt und Sie werden meistens sehen, dass es etwas verbrennt. Das Gesetz von Energie und Material ist immer noch gültig: Kein Material oder Energie erscheint oder verschwindet, sondern verwandelt sich.

1
Alex Paniutin

Sie haben Inline in C99. Vielleicht mögen Sie ctors, aber das Geschäft, dtors richtig zu machen, kann chaotisch sein. Wenn der verbleibende einzige Grund, C nicht zu verwenden, Namespaces sind, würde ich mich wirklich an C89 halten. Dies liegt daran, dass Sie es möglicherweise auf eine etwas andere eingebettete Plattform portieren möchten. Sie können später damit beginnen, in C++ mit demselben Code zu schreiben. Beachten Sie jedoch Folgendes, wobei C++ KEINE Obermenge von C ist. Ich weiß, dass Sie sagten, Sie hätten einen C89-Compiler, aber dieser C++ - Vergleich mit C99 wird trotzdem durchgeführt, da beispielsweise das erste Element für jedes C seit K & R zutrifft.

sizeof 'a'> 1 in C, nicht in C++. In C haben Sie VLA-Arrays variabler Länge. Beispiel: func (int i) {int a [i]. In C haben Sie VAM-Variablenarray-Mitglieder. Beispiel: struct {int b; int m [];}.

1
hept

Im Allgemeinen nicht. C++ ist eine super Menge von C. Dies gilt insbesondere für neue Projekte.

Sie sind auf dem richtigen Weg, um C++ - Konstrukte zu vermeiden, die in Bezug auf CPU-Zeit und Speicherbedarf teuer sein können.

Beachten Sie, dass einige Dinge wie Polymorphismus sehr wertvoll sein können - das sind im Wesentlichen Funktionszeiger. Wenn Sie sie brauchen, setzen Sie sie mit Bedacht ein.

Eine gute (gut konzipierte) Ausnahmebehandlung kann Ihre eingebettete App zuverlässiger machen als eine App, die Dinge mit herkömmlichen Fehlercodes behandelt.

1
Foredecker

Das Buch C++ für Spieleprogrammierer enthält Informationen dazu, wann die Codegröße aufgrund von Funktionen in C++ erhöht wird.

1
zooropa

Bei Problemen mit der Speicherzuweisung kann ich die Verwendung der Quantum-Plattform und ihres Zustandsmaschinenansatzes empfehlen, da sie alles zuordnet, was Sie zum Zeitpunkt der Initialisierung benötigen. Es hilft auch, Konfliktprobleme zu lindern.

Dieses Produkt läuft sowohl auf C als auch auf C++.

0
GregC

Unterschiedlicher Antwortbeitrag zu einem anderen Aspekt der Frage:

"malloc"

Einige frühere Antworten sprechen ziemlich viel darüber. Warum glaubst du überhaupt, dass dieser Anruf existiert? Für eine wirklich kleine Plattform ist malloc in der Regel nicht verfügbar oder auf jeden Fall optional. Das Implementieren der dynamischen Speicherzuweisung ist in der Regel sinnvoll, wenn sich im unteren Bereich Ihres Systems ein RTOS befindet - bis dahin ist dies jedoch nur gefährlich.

Sie können sehr weit kommen, ohne es. Denken Sie nur an all die alten FORTRAN-Programme, die nicht einmal einen richtigen Stack für lokale Variablen hatten ...

0
jakobengblom2

Das hängt vom Compiler ab.

Nicht alle eingebetteten Compiler implementieren C++ vollständig, und selbst wenn dies der Fall ist, sind sie möglicherweise nicht in der Lage, Code Bloat zu vermeiden (was bei Vorlagen immer ein Risiko darstellt). Testen Sie es mit ein paar kleineren Programmen, um festzustellen, ob Probleme auftreten.

Aber bei einem guten Compiler gibt es keinen Grund, C++ nicht zu verwenden.

0
jalf

Ich habe gerade ein Beispiel für die Verwendung von ISO C++ für die Embedded-Entwicklung gefunden, das für jemanden interessant sein könnte, der die Entscheidung trifft, wann immer er C++ oder C verwendet.

Es wurde von Bjarne Stroustrup zur Verfügung gestellt auf seiner Homepage :

Ein Blick darauf, wie ISO C++ für die Programmierung ernsthafter eingebetteter Systeme verwendet werden kann, ist in den C++ - Codierungsstandards für JSF-Luftfahrzeuge zu finden.

0
Piotr Czapla

Es gibt eine Reihe verschiedener Controller-Hersteller auf der ganzen Welt. Wenn Sie sich deren Design und die Anweisungssätze ansehen, die für die Konfiguration benötigt werden, kann dies zu Problemen führen. Der Hauptnachteil der Assemblersprache ist, dass die Maschine/Architektur abhängig ist. Es ist sehr wichtig, dass ein Entwickler auswendig alle Anweisungen befolgt, um die Codierung für verschiedene Controller durchzuführen. Dies ist der Grund, warum C in der Embedded-Entwicklung immer beliebter wurde, da C hoch genug ist, um die Algorithmen und Datenstrukturen von hardwareabhängigen Details zu abstrahieren, wodurch der Quellcode auf eine Vielzahl von Zielhardware- und architekturunabhängigen Sprachen portierbar wird und sehr einfach zu verarbeiten ist konvertieren und pflegen Sie den Code. Es gibt jedoch einige Hochsprachen (objektorientiert) wie C, C++, Python, Java usw.), die sich so weiterentwickeln, dass sie in der Entwicklung eingebetteter Systeme eine Rolle spielen.

0