Forum: Mikrocontroller und Digitale Elektronik C++ für Embedded: ab welchen Prozessormerkmalen?


von Graphical User (Gast)


Lesenswert?

Ich lese gelegentlich, dass 8-Bit MCUs nicht optimale Zielplattformen 
für C++ Compiler seien, allerdings weiß ich nicht genau wieso. Frage: 
welche Kriterien sollten demnach für den Einsatz von C++ erfüllt sein 
und was macht den Unterschied aus (Anforderungen C++ vs. C)?

von Bronco (Gast)


Lesenswert?

Graphical User schrieb:
> allerdings weiß ich nicht genau wieso.

Ich auch nicht.
Ich programmiere meine AVRs in C++ und das geht sehr gut. Man kann in 
C++ deutlich besser kapseln als in C (mit Klassen und Vererbung) und der 
vom Compiler erzeugte Object-Code wird bei richtiger Anwendung auch 
nicht schlechter.

von TestX .. (xaos)


Lesenswert?

das problem sind die dinge wie "new" oder "malloc" .. das geht auf solch 
kleinen platformen schief ..

von Sam P. (Gast)


Lesenswert?

"new" ist das größte Problem, äquivalent zu "malloc" in C.

Auf Systemen mit so wenig RAM ist der Overhead von malloc/new im 
Allgemeinen inakzeptabel. Dazu kommt, dass Objekte häufig als Pointer 
übergeben/verwaltet werden, was bei Klassen, die nur wenige Bytes 
umfassen, zu weiterem Overhead führt. Es gibt noch mehr solcher 
Beispiele.

Wenn man sich dessen bewusst ist und generell ein Verständnis dafür hat, 
welches C++-Feature welche Ressourcen wie benutzt, dann ist C++ auch für 
kleinste µCs geeignet. Man tappt halt leicht in Ressourcenfallen, gerade 
was RAM-Nutzung angeht.

von Peter D. (peda)


Lesenswert?

Der Hauptunterschied ist nur die andere Syntax.
In C++ ist es oftmals schwer zu erkennen, was ein Ausdruck macht und 
welche Ressourcen er belegt. Man muß darauf vertrauen, daß es aus dem 
Namen des Ausdrucks hervor geht.

Ansonsten kann man in C und in C++ auf dem MC effiziente oder 
verschwenderische Programme schreiben.


Peter

von Bronco (Gast)


Lesenswert?

Sam P. schrieb:
> Wenn man sich dessen bewusst ist und generell ein Verständnis dafür hat,
Ja, das braucht es auf jeden Fall, aber sowohl in C++ als auch in C.
Man kann auch in C viel Quatsch machen, z.B.
1
void irgendwas(void)
2
{
3
  char buffer[10000];  // was versteh ich schon vom Stack???
4
  (...)
5
}

von Manateemoo (Gast)


Lesenswert?

Andi D. schrieb:
> das problem sind die dinge wie "new" oder "malloc" .. das geht auf solch
> kleinen platformen schief ..

Ab wie viel RAM lasst sich der Heap halbwegs vernünftig einsetzen? 
Gibt's da Erfahrungswerte?

von Peter D. (peda)


Lesenswert?

Manateemoo schrieb:
> Ab wie viel RAM lasst sich der Heap halbwegs vernünftig einsetzen?

Das hat mit der RAM Größe nichts zu tun. Die Frage ist, warum kann die 
Größe erst zur Laufzeit bestimmt werden?

Ein MC hat in der Regel keine Alternative, wenn malloc fehl schlägt. 
Also muß er soviel RAM haben, wie maximal benötigt wird. Und dann kann 
dieser bereits zur Compilezeit reserviert werden.


Peter

von Bronco (Gast)


Lesenswert?

Manateemoo schrieb:
> Ab wie viel RAM lasst sich der Heap halbwegs vernünftig einsetzen?
> Gibt's da Erfahrungswerte?

Angenommen, Du hast 1kB RAM und zwei Funktionalitäten, die jeweils 
600Bytes allokieren wollen. Dann mußt Du dafür sorgen, daß immer nur 
eine arbeiten darf, während die andere warten muß. Jede mehr 
Funktionalitäten dazu kommen, umso schwieriger wird es, das zu 
beherrschen.

Mit statischer Speicherverwaltung hingegen kannst Du das gar nicht 
verwirklichen, denn der Linker/Locater kann nicht 2x600Byte in 1kB 
unterbringen. Er zwingt Dich, mehr Speicher einzusetzen. Dafür kannst Du 
aber auch sicher sein, daß das immer und unter allen Umständen 
funktionieren wird.

von xfr (Gast)


Lesenswert?

Klar kann man das verwirklichen: Man allokiert statisch 600 Byte und 
beide Funktionen nutzen diesen Speicher. Natürlich darf nur jeweils eine 
Funktion gleichzeitig damit arbeiten, aber das ist im dynamischen Fall 
ja auch so.

Ein Problem hat man dagegen bei folgendem Szenario:
- Funktion 1 benötigt 599 Byte
- Funktion 2 benötigt 600 Byte
- Funktion 3 benötigt 100 Byte
Jede Funktion allokiert ihren Speicher dynamisch.

Jetzt läuft:
- Funktion 1: Bekommt Byte 0-598
- Funktion 3: Bekommt Byte 599-698
- Funktion 1: Gibt Byte 0-598 frei
- Funktion 2: Bekommt keinen Speicher mehr, weil keine 600 Byte am Stück 
frei sind.

Obwohl Funktion 1 und Funktion 2 nicht gleichzeitig laufen, geht es 
schief. Aus diesem Grund (Fragmentierung) vermeidet man auf 
Mikrocontrollern normalerweise dynamische Speicherallokation.

Am ehesten kann man es imo noch machen, wenn die allokierten Häppchen 
alle die gleiche Größe haben. Oder wenn man garantieren kann, dass immer 
nur eine Funktion läuft, die dynamischen Speicher verwendet und sie ihn 
am Ende komplett freigibt. Aber dann könnte sie genauso auf einem 
gemeinsamen statischen Speicher arbeiten. In anderen Fällen wird der 
Speicher mit hoher Wahrscheinlichkeit früher oder später zu sehr 
fragmentiert sein und eine Anforderung schief gehen.

von xfr (Gast)


Lesenswert?

xfr schrieb:
> Aus diesem Grund (Fragmentierung) vermeidet man auf
> Mikrocontrollern normalerweise dynamische Speicherallokation.

Man verwendet natürlich normalerweise keinen dynamischen Speicher.

von Manateemoo (Gast)


Lesenswert?

Das mit der Fragmentierung ist mir bewusst. Ich frage mich nur ab wann 
Dynamischer Speicher sinnvoll funktioniert.
Ich denke eher an eine Cortex M3 mit ca. 1MB Ram und nicht an ein 
8-Bitter mit 2k Ram.
Oder ist es ohne MMU (z.B. Virtueller Speicher) einfach nicht vernünftig 
drin?

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Aber der Compiler müsste doch die dynamische Verwaltung auf einen 
statische Verwaltung abbilden können?

von Peter II (Gast)


Lesenswert?

Stefan Helmert schrieb:
> Aber der Compiler müsste doch die dynamische Verwaltung auf einen
> statische Verwaltung abbilden können?
wie soll er denn das machen?

size_t x = lese_daten_von_irgendwo();
void* p = malloc( x );

woher soll er denn wissen wieviel platz ein einplanen soll?

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Peter II schrieb:
> woher soll er denn wissen wieviel platz ein einplanen soll?

Da der Speicher nach oben hin begrenzt ist, muss das Konzept ja schon 
eine obere Grenze kennen, sonst würde auch bei dynamischer Verwaltung 
der Speicher überlaufen. Und aus dieser Grenze, kann das ja gewonnen 
werden.

von Zedd (Gast)


Lesenswert?

Aber wenn man die Klassen schreibt und nicht "dynamisch" erzeugt, weil 
der Syntax einfach brauchbarer ist als structs mit Funktionen zu 
verheiraten?!
Also wenn man vor der Hauptschleife schon alle news getätigt hat, weil 
man einfach nur etwas übersichtlicher Programmieren will?!

Natürlich muss man dabei selbst den Speicher mitzählen und sich 
wahrscheinlich eine entsprechende größer ausfallende Tolleranz als in C 
lassen.
Wieso soll das nicht gehen?

von Steel (Gast)


Lesenswert?

Zedd schrieb:
> Aber wenn man die Klassen schreibt und nicht "dynamisch" erzeugt, weil
>
> der Syntax einfach brauchbarer ist als structs mit Funktionen zu
>
> verheiraten?!
>
> Also wenn man vor der Hauptschleife schon alle news getätigt hat, weil
>
> man einfach nur etwas übersichtlicher Programmieren will?!
>
>
>
> Natürlich muss man dabei selbst den Speicher mitzählen und sich
>
> wahrscheinlich eine entsprechende größer ausfallende Tolleranz als in C
>
> lassen.
>
> Wieso soll das nicht gehen?


Wozu soll man mit dem Knüppel was in Klassen prügeln ohne dass es 
notwendig ist? Wenn man richtig C kann, dann kann man damit genauso 
übersichtliche Programme schreiben.

C++ macht nur Sinn, wenn man von Objekten zur Laufzeit neue Instanzen 
bilden kann bzw. muss. Das geht halt auf einem uC nicht sinnvoll und man 
braucht für die meisten uC Anwendungen keine objektorientierten Ansätze.

von Dr. Sommer (Gast)


Lesenswert?

> Aber wenn man die Klassen schreibt und nicht "dynamisch" erzeugt, weil
> der Syntax einfach brauchbarer ist als structs mit Funktionen zu
> verheiraten?!
Ja genau so ;-)
> Also wenn man vor der Hauptschleife schon alle news getätigt hat, weil
> man einfach nur etwas übersichtlicher Programmieren will?!
Halt nicht mit "new", sondern statisch anlegen...
> Natürlich muss man dabei selbst den Speicher mitzählen und sich
> wahrscheinlich eine entsprechende größer ausfallende Tolleranz als in C
> lassen.
> Wieso soll das nicht gehen?
GEHEN tut das alles - man kann malloc() auch auf einem Mikrocontroller 
compilen/einsetzen - nur wird es je nach Anwendung wahrscheinlich 
ziemlich schnell nicht mehr funktionieren, weil der Speicher zu 
fragmentiert ist, und kein unfragmentierter Speicher mehr frei ist.

Steel schrieb:
> Wozu soll man mit dem Knüppel was in Klassen prügeln ohne dass es
> notwendig ist? Wenn man richtig C kann, dann kann man damit genauso
> übersichtliche Programme schreiben.
Eben nicht, dank virtuellen Funktionen, Vererbung etc. kann man in C++ 
übersichtlicher & hübscher programmieren - und das ist dann auch 
Fehler-sicherer, weil der Compiler das macht, und man nicht alles von 
Hand basteln muss.

> C++ macht nur Sinn, wenn man von Objekten zur Laufzeit neue Instanzen
> bilden kann bzw. muss.
Nein. Man kann die auch wunderbar statisch anlegen. Habe ich auf einem 
µC-Projekt (STM32F407) gemacht und der Code ist wunderhübsch.
> Und man braucht für die meisten uC Anwendungen keine objektorientierten Ansätze.
brauchen tut man das theoretisch nie, aber einfacher gehts so oft. 
Falls man weiß was man tut.

von xfr (Gast)


Lesenswert?

Ein Vorteil von C++ auf Mikrocontrollern ist imo, dass man verschiedene 
Implementierungen der gleichen Schnittstelle nebeneinander nutzen kann. 
Das geht in C nur umständlich über Funktionspointer.

Daher hat man in C++ schon bessere Möglichkeiten, seine Module zu 
kapseln und austauschbarer zu machen. Das volle Potenzial lässt sich 
aber wie gesagt erst mit dynamischen Objekten nutzen, die man auf nem 
Mikrocontroller normalerweise nicht hat und auch nicht braucht.

von EmbededC++ (Gast)


Lesenswert?

auch auf AVR kann C++ per Template/Overloading elegante Programme 
bescheren.
Und Objekte über Pointer führt bei AVR zur kürzeren indizierten 
Addressierung und damit kürzeren Programmen.
Ob C oder C++, wichtig ist daß man's kann!

von PittyJ (Gast)


Lesenswert?

Ich habe C++ auf kleinen TI-Controller gemacht (F2810).
Alle new's natürlich vor der Hauptschleife. Aber die Konstruktoren sehen 
einfach sauber aus.
Dann hatte ich eine Basis SPI-Klasse, die an die einzelnen HW 
Sensor-Klassen vererbt wurden.
Die Datenkapselung in C++ ist sauberer als in C.

Ich würde nie wieder auf nur C zurückgehen.

von Sam P. (Gast)


Lesenswert?

Steel schrieb:
> Wozu soll man mit dem Knüppel was in Klassen prügeln ohne dass es
> notwendig ist? Wenn man richtig C kann, dann kann man damit genauso
> übersichtliche Programme schreiben.

Gegenfrage: Warum nimmt man nicht eine Sprache, die einem extra 
Hilfsmittel für die Übersichtlichkeit an die Hand gibt?

Das dumme ist, dass C++ komplex ist. Sehr komplex. Man muss sich bewusst 
beschränken. Aber dafür muss man dann nicht mehr alles "zu Fuß" machen. 
Irgendwann bastelt man sich in C nämlich auch was objektorientiertes, 
und dann wird C umständlich.

Beschränkt man sich auf die Kernfunktionen und geht sparsam mit "new" um 
(bzw. verzichtet völlig), dann ist C++ übersichtlicher und kann sogar 
effizienter sein als C, da der Compiler über Klassen und Sichtbarkeit 
mehr Informationen bekommt, was wo wie verwendet werden kann. Geht man 
falsch ran, dann ist es unverständlicher und lahmer Murks.

Und so nebenbei, bei den technischen Daten moderner µCs geht so einiges. 
Die größeren haben zig kB RAM, da lohnt sich dynamische 
Speicherverwaltung. Derzeit schreibe ich einen LISP-Interpreter für SoCs 
ab 64k RAM, der sogar -schock- Garbage Collection hat!

von xfr (Gast)


Lesenswert?

PittyJ schrieb:
> Alle new's natürlich vor der Hauptschleife.

Warum dann überhaupt mit new? Man kann auch in C++ Objekte statisch 
anlegen.

von El Prozzo (Gast)


Lesenswert?

Ich wuerde auch schon auch Echtzeitgruenden keinen dynamischen Speicher 
einsetzen, auch wenn ich genuegend RAM haette.

von (prx) A. K. (prx)


Lesenswert?

xfr schrieb:
> Warum dann überhaupt mit new? Man kann auch in C++ Objekte statisch
> anlegen.

Sogar besser als in C, weil man über Templates Puffergrössen 
parametrisieren kann ohne dynamisch allozieren zu müssen. In C ist das 
weit weniger elegant. Wobei man Templates auch einsetzen kann, ohne 
dabei den Code über Gebühr zu vervielfachen.

Allerdings hilft es, wenn man eine Vorstellung davon hat, was für Code 
ungefähr hinter den C++ Features steht.

von Gerd E. (robberknight)


Lesenswert?

Und Finger weg von der C++ Standardbibliothek!

Sowas harmlos aussehendes wie

int i;
std::cout << "counter: " << i << std::endl;

haut Dir Ruck Zuck Dein Flash voll (wenn es auf Deinem Embedded-System 
überhaupt unterstützt wird).

von EmbededC++ (Gast)


Lesenswert?

Oder ist auch nicht länger als printf, wenn für embeded implementiert 
und nicht einfach von den RAM-Milliardären übernommen. Bei Gelegenheit 
muß ich doch mal was posten...

von c++held (Gast)


Lesenswert?

A. K. schrieb:
> Sogar besser als in C, weil man über Templates Puffergrössen
> parametrisieren kann ohne dynamisch allozieren zu müssen.

Ich bitte um ein Beispiel, das klingt etwas exotisch...

> In C ist das weit weniger elegant. Wobei man Templates auch einsetzen
> kann, ohne dabei den Code über Gebühr zu vervielfachen.

Jede Verwendung wird vom Compiler für diese Objekt speziell impementiert 
-> der code verdoppelt sich. Entscheidend aber ist die 
Wiederverwendbarkeit des getesteten! source codes.

Auf einige Punkte möchte man nicht mehr verzichten. Vererbung, 
Überschreiben, Slicing, verwendung von Referenzen und Konstruktoren, 
eine eigene template Lib. und natürlich eine vernüftige Heap-verwaltung

von herbert (Gast)


Lesenswert?

> -> der code verdoppelt sich. Entscheidend aber ist die
> Wiederverwendbarkeit des getesteten! source codes.

Der Code für die Methoden muss eigentlich nicht verdoppelt werden. 
Lediglich die Attribute braucht jedes Object neu.

von herbert (Gast)


Lesenswert?

>Lediglich die Attribute braucht jedes Object neu.

Kleine Korrektur: Nicht jedes Object, sonderen jede Instanz eines 
Objects.

von (prx) A. K. (prx)


Lesenswert?

c++held schrieb:
> Ich bitte um ein Beispiel, das klingt etwas exotisch...

Auf's Prinzip eingedampft:
1
class UARTbase {
2
public:
3
    enum Parity { None, Even, Odd, Mark, Space };
4
    enum Error { Empty=-1, Overrun=-2, Parity=-3, Framing=-4, Break=-5 };
5
6
    void rate (unsigned rate);
7
    void parity (int parity);
8
9
    void clear ();
10
    void set_break ();
11
    void clear_break ();
12
13
    int  get (bool wait);
14
    void put (char c);
15
    void puts (const char *);
16
    void putu (unsigned value, int ndigits=0, int radix=10);
17
    void puti (int value, int ndigits=0);
18
    void flush ();
19
20
    void interrupt ();      // interrupt handler
21
protected:
22
    UARTbase (int no, uint8_t *rxp, int rxsz, uint8_t *txp, int txsz)
23
      { init(no, rxp, rxsz, txp, txsz); }
24
    void init (int no, uint8_t *rxp, int rxsz, uint8_t *txp, int txsz);
25
private:
26
    static UARTbase *   objp[UART_COUNT];    // UART index to object
27
    volatile UART_t  *  uart;
28
    uint16_t            rxsize, txsize;
29
    volatile uint8_t  * rxbuf, *txbuf;
30
};
31
32
void
33
UARTbase::init(int no, uint8_t *rxp, int rxsz, uint8_t *txp, int txsz)
34
{
35
    uart = &UART(no);
36
    objp[no] = this;
37
    rxsize = rxsz; rxbuf = rxp;
38
    txsize = txsz; txbuf = txp;
39
}
40
41
42
template<int no, int rxsz, int txsz>
43
class UARTc : public UARTbase {
44
public:
45
    UARTc () : UARTbase(no, rxb, rxsz, txb, txsz) {}
46
protected:
47
    uint8_t rxb[rxsz], txb[txsz];
48
private:
49
    static void irq() IRQ_FUNCTION;
50
};
51
52
template<int no, int rxsz, int txsz>
53
void
54
UARTc<no,rxsz,txsz>::irq()
55
{
56
    UARTbase::objp[no]->interrupt();
57
}
und der Anwendung steht global:
1
UARTc<0,64,64>   uart0; // UART Kanal 0, 64/64 Bytes Puffer
2
UARTc<1,256,16>  uart1; // UART Kanal 1, 256/16 Bytes Puffer

> Jede Verwendung wird vom Compiler für diese Objekt speziell impementiert
> -> der code verdoppelt sich.

Yep, aber im obigen Beispiel ist das Template ein Wrapper um eine 
normale Basisklasse, in der fast der gesamte Code steckt. 
Interrupt-Handler inklusive. Im Template steckt kaum Code, weshalb sich 
sehr wenig verdoppelt.

Das Template wird hier nur benötigt, um die besagten Puffer anzulegen 
und den kanalspezifischen Interrupt-Handler auf den generischen Handler 
durchzureichen.

> natürlich eine vernüftige Heap-verwaltung

Der Witz in diesem Beispiel ist, dass dafür kein Heap gebraucht wird.

von Christian B. (casandro)


Lesenswert?

Mal zur Info wie malloc und free typischerweise implementiert wird:

Speicher: Nehmen wir mal an, das wären 8 Bit Worte und wir hätten einen 
8 Bit Adressbereich, damit wird das übersichtlicher. Wir haben einen 
String ABCD in einem Speicherbereich der mit Malloc alloziert wurde und 
ab Adresse 236 beginnt

234: #???  Zeiger zum vorherigen Datenblock
235: #243  Zeiger zum nächsten Datenblock
236: A
237: B
238: C
239: D
240: #0
241: #236  Zeiger zum vorherigen Datenblock
242: #???  Zeiger zum nächsten Datenblock
243: ????  Daten des nächsten Datenblocks

Man hat also eine doppelt verkettete Liste. Wohin jetzt die Zeiger genau 
zeigen ist implementationsabhängig. Ebenso wie denn ein freier Block 
gekennzeichnet wird. Bei einem free wird einfach der Block auf "frei" 
gesetzt, und gegebenenfalls mit freien Blöcken vorher und nachher 
vereinigt. Und natürlich hat man in der Regel keine 8-Bit Pointer 
sondern mindestens 15 Bit. (16Bit-1Bit für Kennung ob frei ist) Wie 
schon gesagt, das ist nur, damit es übersichtlicher wird.

Was bei C++ noch an zusätzlichen Aufwand anfällt ist eine Tabelle mit 
den virtuellen Methoden einer Klasse, damit Du die aufrufen kannst ohne 
den Typ der Klasse genau wissen zu müssen. Ich bin kein Freund von C++, 
viele der Sachen kriegst Du auch einfacher mit einfacheren Sprachen hin.

von (prx) A. K. (prx)


Lesenswert?

Christian Berger schrieb:
> Was bei C++ noch an zusätzlichen Aufwand anfällt ist eine Tabelle mit
> den virtuellen Methoden einer Klasse, damit Du die aufrufen kannst ohne
> den Typ der Klasse genau wissen zu müssen.

Das fällt nur an, wenn virtuelle Methoden verwendet werden. Und der 
Aufwand dafür ist nicht wesentlich grösser, als der, den man für eine 
analoge Implementierung in C reinsteckt.

Ohne virtuelle Methoden und bei abgeschalteter RTTI entsteht kein 
Zusatzaufwand gegenüber C.

> Ich bin kein Freund von C++,
> viele der Sachen kriegst Du auch einfacher mit einfacheren Sprachen hin.

Jedem Tierchen sein Pläsierchen. Ich empfinde C++ zwar auch nicht als 
wirklich gelungenen Entwurf, kann darin aber einiges einfacher und vor 
allem leichter wiederverwendbar und übersichtlicher gestalten als in C. 
Andere Leute mögen das anders sehen.

von I. J. (Gast)


Lesenswert?

wow,

ich muss gestehen von den Interna was und wie da wo in C oder C++ landet 
hab ich keinen blassen aber ich progge einfach gern in C++ ... ist halt 
mein Pläsierchen :-D es geht auf jeden Fall auf dem 8-bitter wie auf 
32-bittern
wobei C++ wie es mir scheint dann doch ein bisschen hungriger nach FLASH 
und RAM ist aber es hält sich in Grenzen und die Vorteile wiegen das 
meiner Meinung nach auf.

guckst du hier: http://www.avr-cpp.de und http://www.mySTM32.de

meine lieblings Tutorials >>*schäm*<<

Gruß J.

von Strubi (Gast)


Lesenswert?

Moin,

ne Menge Leute haben sich nu die Finger fransig getippt, aber keiner hat 
bisher erwähnt, dass C++ keinen richtigen API-Standard besitzt. Im 
Gegensatz zu C. Sprich: Die Symbol-Dekorationen ("mangling") macht jeder 
C++-Compiler anders. Einen Quasi-Standard hat man nur mit GCC.

Deswegen gilt bei grösseren Projekten in meiner Umgebung immer noch:
- Libraries, und Kernels werden in C geschrieben
- GUIs, grössere Userspace-Programme in C++ und Python

Klar kann man über eine C++-Lib einen C-API layer setzen, aber die 
Library ist damit noch nicht "sauber". Es gibt ne Menge bekannter 
Gründe, dass Kernels wie Linux niemals in C++ geschrieben sind. Bei 
einigen Compilern ist es ziemlich mühsam, den C++-Ballast, den man nicht 
haben will, abzuspecken, da kann man sie gleich sauber in C schreiben.

Mit einem grossen Fragezeichen ist immer noch behaftet, ob sich C++ 
amortisiert (hat). Für mich persönlich geht's mit in C handcodierten 
"Objektklassen" und entsprechenden Python-Wrappern immer noch am 
stabilsten und läuft auch noch auf einem uC. (Anmerkung: bin schon seit 
20 Jahren mit C++ "dabei"). Im Gegensatz zu Python verletzt C++ einige 
"keep it simple"-Prinzipien und verleitet Anfänger, ne Menge falsch zu 
machen.

Letztendlich soll jeder so machen, wie er am besten zum Ziel kommt, nur 
gibt es schon genannte Aspekte zur Kollaborative und nicht zuletzt in 
der Industrie auch zur Code-Verifikation und -Zertifizierung.

Grüsse,

- Strubi

von herbert (Gast)


Lesenswert?

>aber keiner hat
>bisher erwähnt, dass C++ keinen richtigen API-Standard besitzt.

Ich muss gestehen, dass ich deine Aussage nicht verstehe. Kannst Du mal 
ein konkretes Beispiel machen?

von Rolf Magnus (Gast)


Lesenswert?

Gerd E. schrieb:
> Sowas harmlos aussehendes wie
>
> int i;
> std::cout << "counter: " << i << std::endl;
>
> haut Dir Ruck Zuck Dein Flash voll (wenn es auf Deinem Embedded-System
> überhaupt unterstützt wird).

EmbededC++ schrieb:
> Oder ist auch nicht länger als printf, wenn für embeded implementiert
> und nicht einfach von den RAM-Milliardären übernommen.

Eine minimalistische Implementation, die noch ein paar im Hintergrund 
ablaufende Dinge wie die Locales weglässt, wäre meiner Meingung nach 
sogar deutlich sparsamer als printf, da die Ausgaben ja alle über 
entsprechende separate Operator-<<-Implementationen gemacht wird. Der 
wesentliche Vorteil: Bei printf muß der Ausgabecode für alle 
unterstützen Datentypen mit gelinkt werden, auch für die, die im 
Programm gar nicht genutzt werden. Deshalb gibt es beim AVR ja auch als 
Krücke die verschiedenen printf-Varianten, wo man per 
Linker-Kommandozeile zwischen verschiedenen Kompromissen wählen muß. 
Dazu kommt bei printf allgemein noch die Notwendigkeit für den 
Format-String-Parser.
Bei cout dagegen gibt's für jeden Datentyp eine separate Funktion, die 
einfachen Typen können auch gleich inline abgefrühstückt werden. Dadurch 
wird der Code kleiner, und man kann automatisiert dafür sorgen, daß 
wirklich nur genau die Konvertierungen im Programm landen, die auch 
benutzt werden. Und ich wüßte auch nicht, warum das langsamer sein 
sollte. Da kein Formatstring geparst werden muß, dürfte es eher 
schneller sein.

A. K. schrieb:
> xfr schrieb:
>> Warum dann überhaupt mit new? Man kann auch in C++ Objekte statisch
>> anlegen.
>
> Sogar besser als in C, weil man über Templates Puffergrössen
> parametrisieren kann ohne dynamisch allozieren zu müssen. In C ist das
> weit weniger elegant.

Wie meinst du das? Bei deiner Beschreibung denke ich an sowas:
1
uint8_t buffer[BUF_SIZE];

Aber du scheinst noch was anderes zu meinen.

A. K. schrieb:
> Christian Berger schrieb:
>> Was bei C++ noch an zusätzlichen Aufwand anfällt ist eine Tabelle mit
>> den virtuellen Methoden einer Klasse, damit Du die aufrufen kannst ohne
>> den Typ der Klasse genau wissen zu müssen.
>
> Das fällt nur an, wenn virtuelle Methoden verwendet werden. Und der
> Aufwand dafür ist nicht wesentlich grösser, als der, den man für eine
> analoge Implementierung in C reinsteckt.

Allerdings landen die Tabellen beim avr-g++ leider unnötigerweise im 
RAM. Oder hat sich das inzwischen geändert?

Strubi schrieb:
> ne Menge Leute haben sich nu die Finger fransig getippt, aber keiner hat
> bisher erwähnt, dass C++ keinen richtigen API-Standard besitzt. Im
> Gegensatz zu C.
> Sprich: Die Symbol-Dekorationen ("mangling") macht jeder
> C++-Compiler anders. Einen Quasi-Standard hat man nur mit GCC.

Du meinst nicht API, sondern ABI. Das stimmt zwar, aber nun erzeugt man 
auf einem kleinen µC selten Programme, bei denen Teile des Code mit 
unterschiedlichen C++-Compilern übersetzt wurden und zusammengelinkt 
werden müssen.
Und daß es in C einen Standard gäbe, stimmt auch nicht. Es gibt auch 
nicht nur name-mangling, sondern auch noch einige weitere Dinge, wie 
z.B. Parameterübergabe oder die Größen der Integer- und Float-Typen. 
Übrigens gibt es z.B. unter Windows auch für C mehrere verschiedene 
Varianten von name-mangling.

> Klar kann man über eine C++-Lib einen C-API layer setzen, aber die
> Library ist damit noch nicht "sauber". Es gibt ne Menge bekannter
> Gründe, dass Kernels wie Linux niemals in C++ geschrieben sind.

Nunja, wenn ich mir die Gründe ansehe, die Linus Torvalds so nennt, sind 
die eher an den Haaren herbeigezogen und zeugen eher davon, daß er sich 
entweder erst gar nicht richtig mit C++ beschäftigt hat und daher auch 
keine Ahnung davon hat oder es einfach nur nicht mag.
Zwischen Kernels und Userspace-Programmen ist sowieso nochmal das 
Systemcall-Interface, so daß man da auch in C noch entsprechende Wrapper 
hat. Und was die Compilierbarkeit mit verschiedenen Compilern angeht, 
ist gerade Linux da ein interessantes Beispiel, da Linus ja keinen Hehl 
draus macht, daß er den Kernel ausschließlich für gcc schreibt und für 
nix anderes, da er sehr regen Gebrauch von gcc-Erweiterungen macht.
Intel hat meines Wissens mal mit erheblichem Aufwand seinen Compiler 
Linux-Kernel-kompatibel gemacht. Ob er das heute auch noch ist, weiß ich 
aber niht.

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Wie meinst du das? Bei deiner Beschreibung denke ich an sowas:

Klar geht das so. Aber das kann man nicht im Treiber selber machen, wenn 
parametrisierbare Grössen oder meherere Instanzen (z.B. mehrere UARTs) 
möglich sein sollen. Daher muss das entweder dynamisch alloziert werden, 
oder der Caller tut es selbst und übergibt den Puffer an die Instanz des 
Treibers.

Beitrag "Re: C++ für Embedded: ab welchen Prozessormerkmalen?"

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Allerdings landen die Tabellen beim avr-g++ leider unnötigerweise im
> RAM. Oder hat sich das inzwischen geändert?

Das ist nun eher eine Frage der konkreten Implementierung als der 
Sprache. Ausserdem geht es hier nicht um riesige Datenmengen. Ich dürfte 
auch unter C++ Anhängern einen gewissen Konsens geben, dass man solche 
Konzepte nicht bei einem ATtiny10 verwendet. Aber bei einem ATmega32 
fällt das nicht mehr gross auf.

von Rolf Magnus (Gast)


Lesenswert?

A. K. schrieb:
> Rolf Magnus schrieb:
>> Wie meinst du das? Bei deiner Beschreibung denke ich an sowas:
>
> Klar geht das so. Aber das kann man nicht im Treiber selber machen, wenn
> parametrisierbare Grössen oder meherere Instanzen (z.B. mehrere UARTs)
> möglich sein sollen. Daher muss das entweder dynamisch alloziert werden,
> oder der Caller tut es selbst und übergibt den Puffer an die Instanz des
> Treibers.

Gut, aber die Verwendung von Templates ändert doch daran nichts.

von (prx) A. K. (prx)


Lesenswert?

Doch. Die Arrays sind Teil des Templates, nicht des Anwendungsprogramms. 
Die Anwendung gibt ans Template die gewünschten Puffergrössen mit und 
die Puffer sind Teil der Instanz. Ist die Instanz statisch, dann auch 
die Puffer. Das Template wiederum ist Teil des Treibers, nicht der 
Anwendung.
1
template<int no, int rxsz, int txsz>
2
    ...
3
    uint8_t rxb[rxsz], txb[txsz]; // Tx/Tx Puffer
4
    ...
5
};

von (prx) A. K. (prx)


Lesenswert?

Man kann so etwas auch weiter generalisieren. Ich hatte es hier bewusst 
weggelassen, aber das kann auch so aussehen:
1
template<int no, int rxsz, int txsz>
2
    ...
3
    GBuffer<uint8_t, rxsz> rxb;
4
    GBuffer<uint8_t, txsz> txb;
5
    ...
6
};
In diesem Fall ist GBuffer<> ein generisches Template für den Umgang mit 
sequentiellen Puffern in Verbindung mit Treibern mit Interrupt-Handlern. 
Braucht man ja öfter mal, nicht nur bei UARTs.

von ansel (Gast)


Lesenswert?

Strubi schrieb:
> Gründe, dass Kernels wie Linux niemals in C++ geschrieben sind.

Einer der schnellsten Microkernel (L4) ist in C++ geschrieben.

von Karl H. (kbuchegg)


Lesenswert?

>> Daher muss das entweder dynamisch alloziert werden,
>> oder der Caller tut es selbst und übergibt den Puffer an die Instanz des
>> Treibers.
>
> Gut, aber die Verwendung von Templates ändert doch daran nichts.

Die Organisation ist anders. In A.K. s Beispiel hat zb der 
Anwendungsprogrammierer keine Chance die Klasse über Puffergrößen 
'anzulügen'. Wieder eine potentielle Fehlerquelle weniger.

Letzen Endes kann keine Programmiersprache zaubern. Alles was man in 
jeder x-beliebigen Programmiersprache machen kann, kann man auch in 
Assembler machen. Höhere Programmiersprachen haben einfach nur den Sinn, 
von dieser Ebene wegzuabstrahieren und den Focus mehr auf 
Softwaretechnik zu legen.


> Was bei C++ noch an zusätzlichen Aufwand anfällt ist eine Tabelle
> mit den virtuellen Methoden einer Klasse, damit Du die aufrufen
> kannst ohne den Typ der Klasse genau wissen zu müssen.

Schon richtig.
Aber was ist die Alternative?
elends lange switch-case Orgien, die über eine Typ Kennung in die 
jeweilige Funktionalität verzweigen. Und wehe du vergisst bei der 
nächsten Programm-Erweiterung auf die Ergänzung eines einzigen 
switch-case auf die neu eingeführte Typkennung.

Wenn man solche Vergleiche macht, dann darf man nicht nur fragen "Was 
kostet mich das in der Sprache X" sondern man muss sich auch fragen "Und 
wie mach ich das in meiner Programmiersprache". Dann merkt man nämlich 
sehr schnell, dass viele C++ Konzepte gar nicht dumm sind, IM VERGLEICH 
zu der Variante, wie man dasselbe in reinem C erreichen würde. Die 
Zusatz-Kosten sind überschaubar (wenn überhaupt) und der Gewinn kann 
beträchtlich sein. 'Kann', muss nicht. Denn der C Weg steht einem ja in 
C++ immer noch offen.

Man kann ALLES was man in C++ machen kann (oder in jeder anderen 
Programmiersprache) auch in C machen (oder in Assembler). Das ist nicht 
die Frage. Die Frage ist: mit welchem Aufwand; mit welchem 
Fehlerpotential; mit welchen Möglichkeiten einer Programmorganisation, 
so dass man das Programm auch in 15 Jahren noch warten und erweitern 
kann ohne dass gleich alles auseinander fällt. Und da hat C++ gegenüber 
C nun mal die Nase vorn.

von Peter D. (peda)


Lesenswert?

A. K. schrieb:
> Yep, aber im obigen Beispiel ist das Template ein Wrapper um eine
> normale Basisklasse, in der fast der gesamte Code steckt.
> Interrupt-Handler inklusive. Im Template steckt kaum Code, weshalb sich
> sehr wenig verdoppelt.

Das mit den Interrupts würde mich mal interessieren, wie das in C++ 
geht.
Ich hätte gedacht, daß ich für die 4 UARTs (ATmega2560) auch 8 
Interrupthandler benötige (USART0_RX .. USART3_RX, USART0_UDRE .. 
USART3_UDRE).

Kannst Du mal den kompletten Code zeigen?


Peter

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:
> Ich hätte gedacht, daß ich für die 4 UARTs (ATmega2560) auch 8
> Interrupthandler benötige (USART0_RX .. USART3_RX, USART0_UDRE ..
> USART3_UDRE).

Der obige Code war für LPC2000 und da gibts nur einen pro UART. Aber das 
Prinzip ändert sich sich nicht sehr. Nur gibts dann eben pro Irq-Typ 
einen Handler in der Basisklasse, also für RX und UDRE. Bei 4 Instanzen 
der Klasse, eine pro UART, sind das dann auch wieder deine 8.

Wie sich das exakt ausformuliert hängt vom Interrupt-Controller und 
dessen Einbindung in die Entwicklungsumgebung ab. Beim VIC der LPC2000 
wird die Adresse des Handlers zur Laufzeit explizit zugewiesen, was die 
Sache programmtechnisch deutlich vereinfacht. Hier steht also 
sinnngemäss als Teil der Initialisierung im Template:
   VicSetVector(..., UARTc<...>::irq);
Wes ich oben wegliess: Es gibt eine Verwaltungstabelle, die die 
Kanalnummer in die Hardware-Adresse und in diesem Fall die Nummer des 
Vektors umsetzt.

Bei anderen Interrupt-Einbindungen wie bei AVR oder CM3 mit fest 
definierten Handler-Namen muss man anders vorgehen. Da kommt man nicht 
drum herum, ausserhalb des Templates Stubs für alle Vektoren der Devices 
vorzubelegen. Also jetzt mal unbeschadet der Namen und der exakten 
Syntax wieder sinngemäss in aller Kürze:
 extern "C" {
   void UART0_RX_vector() _irq_   { UART::objp[0]->rx_handler(); }
   void UART0_UDRE_vector() _irq_ { UART::objp[0]->udre_handler(); }
   void UART1_RX_vector() _irq_   { UART::objp[1]->rx_handler(); }
   ...
 }
Der Trick ist jedesmal, im Irq-Stub über dieses Array an die realen 
Objekte ran zu kommen. In der Verwaltungstabelle stehen beim CM3 
beispielsweise die pro Kanal erforderlichen Bits vom NVIC drin, die ja 
auch gesteuert werden müssen (NB: da ist Bitbanding ganz nützlich).

von Peter D. (peda)


Lesenswert?

@A. K.

Danke für die Antwort.
Ich muß zugeben, daß diese Frage auch mehr theoretischen Charakter 
hatte.
Ich habe zwar alle 4 UARTs benutzt, aber auf völlig unterschiedliche 
Weise:

1.UART:
- im SPI-Mode zum Keyboard (Tasten, Encoder, LEDs)
- arbeitet nur im Interrupt und frischt die Bits für Keypress und 
Encoder auf

2.UART:
- im SPI-Mode als Erweiterungsbus (ADCs, DACs, 74HC595 usw.)

3.UART
- UART zum PC (2 normale FIFOs)

4.UART
- UART zum eDIPTFT43-A (SMALL PROTOKOLL)

Lange Rede, kurzer Sinn: Es ließe sich eh kein gemeinsamer Code nutzen.


Ich habe bei MC-Anwendungen den Eindruck, daß sich nur sehr selten ein 
gemeinsamer Deckel über verschiedene Tasks stülpen läßt. Und das ist ja 
bei C++ der Hauptpunkt.
Bzw. wenn mehrere Tasks gleich sind, geht das auch gut über Schleifen 
oder Arrays.


Peter

von Hans (Gast)


Lesenswert?

Man kann alles was man in C++ kann auch in C machen.. irgendwie... nur 
für "moderne" Design-Patterns ist C++ wesentlich eleganter.

Wenn ich mir Code-Reuse anschaue, ist C++ wesentlich besser geeignet, da 
man eben schöner kapseln kann.

Ich habe in der Arbeit lange gebraucht, aber nun sind so ziemlich alle 
überzeugt, dass C++ einfach schöneren Code ergibt.

und schöner Code ist zu 99% kleiner und schneller wie "hochoptimierter" 
C-Code... Das ist leider Fakt und lässt sich in der Literatur seit Mitte 
der 70er nachlesen.

C++ (und alle Highlevel-Sprachen - C++ ist sowas eigentlich nicht) 
bietet halt dummerweise mehr Möglichkeiten schlechten Code zu 
schreiben...

Dafür ist es strikter typisiert wie C und das ist meiner Einschätzung 
nach im professionellen Umfeld der Hauptvorteil... char  und void  ist 
eben nicht das selbe, auch wenn einem das C glauben lässt ;)

73

von Hans (Gast)


Lesenswert?

Sorry war zu faul um einloggen und hab das pritty-printing vergessen

...
1
char *
 und
1
void *
ist eben nicht das selbe ...

von Peter D. (peda)


Lesenswert?

Das klingt ja alles wunderschön, allein mir fehlt der Zugang.

In C schreibe ich direkt hin, was ich gerade machen will.

In C++ muß ich immer erst zurück ins h-File und ne Klasse anlegen oder 
erweitern. Und dann wieder an die Stelle, wo ich dann die Klasse 
aufrufe.
Das wirkt auf mich nicht sonderlich effizient oder übersichtlich.


In C habe ich gelernt, alles was keinen Code erzeugt, kommt ins h-File. 
Klassen erzeugen aber Code.
Aber sie müssen auch bekannt gemacht werden, also doch ins h-File.
Die Trennung zwischen Deklaration und Definition gilt also in C++ nicht 
mehr.
Ist schon sehr kompliziert das mit dem C++.


Peter

von m.n. (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Das klingt ja alles wunderschön, allein mir fehlt der Zugang.

Ich glaube, es ist die Richtung, aus der man auf seine Probleme kuckt. 
Solange man noch auf die Bits im Statusregister sieht, geht man eher den 
Weg Assembler -> C (== komfortabler Assembler). Bei Controllern, wo man 
die höchstmögliche Leistung herausholen möchte, will man auch die 
Kontrolle über den erzeugten Code behalten.

Bei komplexeren Problemen ist C++ sicherlich unvermeidlich; da 
interessiert auch überhaupt nicht mehr, was im Statusregister des 
Prozessors abläuft und wo sich physikalisch die GByte an RAM befinden.
Die Leute, die die aktuellen, neuen ICEs nicht zum Laufen bekommen, 
kennen wohl auch keine Statusregister mehr :-)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter Dannegger schrieb:
> In C habe ich gelernt, alles was keinen Code erzeugt, kommt ins h-File.

Das sollte man auch in C++ so machen.

> Klassen erzeugen aber Code.

Nein, nicht die Klassendeklaration im h-File. Und die Methodendefinitio-
nen stehen im cpp-File.

Man kann einen Methodenrumpf zwar auch direkt in die Klassendeklaration
schreiben, dann ist die Methode aber implizit als inline deklariert und
erzeugt deswegen ebenfalls keinen Code, zumindest nicht direkt. Code
wird in diesem Fall erst an der Stelle erzeugt, wo die Methode aufgeru-
fen wird, also in einem cpp-File.

Auch in C werden Inline-Funktionen, die in mehreren Modulen benötigt
werden, gerne in h-Files geschrieben.

> Die Trennung zwischen Deklaration und Definition gilt also in C++ nicht
> mehr.

Doch, daran hat sich überhaupt nichts geändert.

> Ist schon sehr kompliziert das mit dem C++.

Es gibt sicher einige Dinge, die in C++ recht kompliziert und schwer zu
durchschauen sind. Die Regeln, was man ins h- und ins cpp-File schreibt,
gehören aber nicht dazu.

von Dr. Sommer (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Das klingt ja alles wunderschön, allein mir fehlt der Zugang.
>
> In C schreibe ich direkt hin, was ich gerade machen will.
>
> In C++ muß ich immer erst zurück ins h-File und ne Klasse anlegen oder
> erweitern. Und dann wieder an die Stelle, wo ich dann die Klasse
> aufrufe.
Auch in C muss man Funktionen zuvor deklarieren, in C++ Funktionen & 
Klassen. Wenn man die Klasse vorher nie verwendet, kann man die auch 
komplett "inplace" an einer Stelle deklarieren & implementieren:
class UART {
  void send (uint8_t byte) { UDR0 = byte; }
};

> Das wirkt auf mich nicht sonderlich effizient oder übersichtlich.
Eben doch - indem man Implementation von Deklaration trennt, kann man im 
.h-File auf einen Blick alle Funktionen und Member-Variablen sehen, ohne 
erst durch eine 2000 Zeilen lange Codedatei zu scrollen... Und damit das 
Interface dieser Klasse, das was den Benutzer der Klasse interessiert.

> In C habe ich gelernt, alles was keinen Code erzeugt, kommt ins h-File.
> Klassen erzeugen aber Code.
Nein. Nur die Funktionen der Klasse. Die Klasse an sich ist nur eine 
"Hilfe" für den Compiler, ähnlich wie structs in C.
> Aber sie müssen auch bekannt gemacht werden, also doch ins h-File.
> Die Trennung zwischen Deklaration und Definition gilt also in C++ nicht
> mehr.
Wie oben gesagt, ist das sehr wohl so.
> Ist schon sehr kompliziert das mit dem C++.
Stimmt, aber es ist nunmal nicht jedes Programm ein LED-Blinker - für 
komplexe Probleme können mächtigere Tools effizienter sein...!

von Hans-Georg L. (h-g-l)


Lesenswert?

Peter Dannegger schrieb:
> ...
> In C++ muß ich immer erst zurück ins h-File und ne Klasse anlegen oder
> erweitern. Und dann wieder an die Stelle, wo ich dann die Klasse
> aufrufe.

Hallo Peter, ich nehme an das du in C auch schon öfter Funktionen mit 
vielen Parametern gehabt hast und diese an Unterfunktionen weiter 
gegeben hast. Also was hast du gemacht ? Du hast dir Structs definiert 
mit den Parametern darin und diese übergeben. Und schon hast du eine 
(methodenlose) Klasse ohne es zu wissen gehabt und musstest ins h File 
zum Ändern der Struktur;).

> Ist schon sehr kompliziert das mit dem C++.

Nö ;)

von (prx) A. K. (prx)


Lesenswert?

Yalu X. schrieb:
> Nein, nicht die Klassendeklaration im h-File. Und die Methodendefinitio-
> nen stehen im cpp-File.

So konsequent aber nur, wenn man Templates als systematischeren 
Nachfolger von komplexen Präprozessor-Makros versteht.

von Peter D. (peda)


Lesenswert?

Yalu X. schrieb:
> Nein, nicht die Klassendeklaration im h-File. Und die Methodendefinitio-
> nen stehen im cpp-File.

Na dann is ja gut.
Ich weiß jetzt auch nicht mehr, warum ich den Eindruck hatte, da stünde 
Code drin. Muß mir mal die Beispiele gründlicher ansehen.


Peter

von xfr (Gast)


Lesenswert?

Peter Dannegger schrieb:
> In C habe ich gelernt, alles was keinen Code erzeugt, kommt ins h-File.

Das machen manche so, ist aber total unsinnig. Ins h-File sollte das 
gehören, was man benötigt, um das dazugehörige c-File von woanders 
verwenden zu können. Also Funktionsdeklarationen, Typedefs und Defines, 
die auch außerhalb des c-Files benötigt werden.

Alles, was nur innerhalb der c-Datei benötigt wird, also z.B. Prototypen 
von statischen Funktionen und interne Defines gehören in die c-Datei.

> Klassen erzeugen aber Code.
> Aber sie müssen auch bekannt gemacht werden, also doch ins h-File.
> Die Trennung zwischen Deklaration und Definition gilt also in C++ nicht
> mehr.

Eine Klassendeklaration ist das gleiche wie die Deklaration von Structs 
oder Funktionensprototypen in C. Die Definition der Methoden (also der 
Code) ist in der cpp-Datei, genau wie C.

Weniger schön ist imo nur, dass private Variablen und Methoden auch ins 
h-File müssen. Das verletzt das Information-Hiding-Prinzip und lässt 
sich afaik nur mit dynamischer Speicherallokierung (Factory-Methode) 
bzw. virtuellen Methoden umgehen.

von (prx) A. K. (prx)


Lesenswert?

xfr schrieb:
> Weniger schön ist imo nur, dass private Variablen und Methoden auch ins
> h-File müssen. Das verletzt das Information-Hiding-Prinzip

Korrekt. Wobei aber genau ebendies eine Voraussetzung darstellt, dass 
man mit auf klassischen einzelnen Quelltexten basierendem Quellcode und 
individueller Übersetzung der Quellcode-Module sehr effizienten Code 
erzeugen und mit statisch oder auf dem Stack allozierten Instanzen statt 
nur im Heap arbeiten kann.

C++ ist ein stilistisch nicht allzu eleganter Kompromiss, keine saubere 
Lösung. Aber immerhin liegt hier im Forum der Fokus auf 
Mikrocontrollern, nicht auf Desktop-GUIs. Da sind Resourcenfragen 
relevanter.

von Hans-Georg L. (h-g-l)


Lesenswert?

xfr schrieb:
> Peter Dannegger schrieb:
>> In C habe ich gelernt, alles was keinen Code erzeugt, kommt ins h-File.
>
> Das machen manche so, ist aber total unsinnig. Ins h-File sollte das
> gehören, was man benötigt, um das dazugehörige c-File von woanders
> verwenden zu können. Also Funktionsdeklarationen, Typedefs und Defines,
> die auch außerhalb des c-Files benötigt werden.
>

bei C++ templates findest du oft alles in einem einzigen h File. Ich 
mags auch lieber getrennt.

@OT
"C++ in embedded systems: Myth and reality"
http://www.eetindia.co.in/ARTICLES/1998FEB/PDF/EEIOL_1998FEB02_EMS_TA.pdf

von Ralf G. (ralg)


Lesenswert?

Peter Dannegger schrieb:
> In C habe ich gelernt, alles was keinen Code erzeugt, kommt ins h-File.

Hans-Georg Lehnard schrieb:
> bei C++ templates findest du oft alles in einem einzigen h File. Ich
> mags auch lieber getrennt.

Ist aber nur die Schablone. Das erzeugt immer noch keinen Code.

von Troll (Gast)


Lesenswert?

Hans-Georg Lehnard schrieb:
> bei C++ templates findest du oft alles in einem einzigen h File. Ich
> mags auch lieber getrennt.

Und wo wird bei Templates der Code erzeugt? - Richtig, bei der 
Verwendung des Codes der Templates (oder der Klassen, die Templates 
benutzen) im .cpp-File.

von (prx) A. K. (prx)


Lesenswert?

Aus heutiger Sicht muss man eigentlich das klassische Prinzip von 
Quellcode-Texten in .h/.c aufgeben und Code in einer Art Datenbank 
platzieren, aus der der Programmierer nur jene Information bezieht, die 
er grad benötigt. Dann löst sich die Frage Interface/Implementierung in 
Luft auf und von anderen Klassen als der grad bearbeiteten sieht man nur 
das Interface.

Sowas gibts natürlich. Und auch basierend auf klassischem Quellcode gibt 
es natürlich Programmierwerkzeuge, die ungefähr dieses Schema 
implementieren. Aber die Frage ist, inwieweit dieses althergebrachte 
Quellcode-Paradigma heute noch zeitgerecht ist. Zumal Compiler heute 
gerne den eigentlichen Übersetzungsschritt dem Linker überlassen, weils 
vorher nicht mehr wirklich gut geht.

von (prx) A. K. (prx)


Lesenswert?

Troll schrieb:
> Und wo wird bei Templates der Code erzeugt? - Richtig, bei der
> Verwendung des Codes der Templates (oder der Klassen, die Templates
> benutzen) im .cpp-File.

Und wo wird bei heutigen Compilern jenseits der µC-Klasse der Code 
erzeugt? Alles miteinander im Linker, jedenfalls wenn man das so will. 
Der eigentliche Compiler liefert nur mehr vorgekauten Zwischencode ab. 
Für Optimierung ist das sehr nützlich.

Nope, hier geht es um die Sicht auf den Quellcode. Nicht an welcher 
Stelle des gesamten Übersetzungsprozesses der Compiler die 
Maschinenbefehle erzeugt.

von Hans-Georg L. (h-g-l)


Lesenswert?

Troll schrieb:
> Hans-Georg Lehnard schrieb:
>> bei C++ templates findest du oft alles in einem einzigen h File. Ich
>> mags auch lieber getrennt.
>
> Und wo wird bei Templates der Code erzeugt? - Richtig, bei der
> Verwendung des Codes der Templates (oder der Klassen, die Templates
> benutzen) im .cpp-File.

Für den Compiler machts keinen Unterschied ...

Mir ging es aber um das Lesen von Quellcodes für Menschen.

von Troll (Gast)


Lesenswert?

A. K. schrieb:
> Nope, hier geht es um die Sicht auf den Quellcode. Nicht an welcher
> Stelle des gesamten Übersetzungsprozesses der Compiler die
> Maschinenbefehle erzeugt.

Dann sehe ich aber keinen prinzipiellen Unterschied zu C.
1
#define GROESSER(a,b) (a > b)

und

[c]template<T> bool Groesser(T a, T b) { return a > b; }

stehen beide im .h File und halten dort den entsprechenden Code.

Klar verleiten Template-Funktionen (gerade wegen der nicht Vorhandenen 
Notwendigkeit, jede Zeile mit einem '\' abzuschließen) dazu, sie 
umfangreicher zu gestalten, als C-Makros, aber letzendlich gab es diesen 
Bruch in der Aufteilung Deklaration->.h und Code->.c(pp) aus 
Programmierersicht ("Menschen", "Sicht auf den Quellcode") schon vor 
C++.

von (prx) A. K. (prx)


Lesenswert?

Eben. Wie ich vorhin darlegte halte ich die Trennung in getrennten 
Quellcode für Interface und Implementierung für mittlerweile veraltet. 
Im Grunde reicht ein Quellcode für das ganze Modul, aus dem sich 
Programmierumgebung und Compiler die für sie passenden Elemente 
rauspicken. Zumal dort auch die Doku gut hinein passt.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Zur ursprünglichen Frage:

Für mich stellt sie sich gar nicht :)

Ob ich etwas lieber in C oder in C++ schreibe, hängt fast ausschließlich
von der Programmgröße ab. Alles, was maximal ein paartausend Zeilen lang
ist, habe ich in C schneller hingeschrieben. Eine Klassenstruktur spielt
ihre Vorteile erst bei größeren Programmen aus. Dann ist C++ die bessere
Wahl. Ein weiterer großer Vorteil von C++ sind die von der STL und den
Boost-Libraries zur Verfügung gestellten Highlevel-Datentypen, die das
Programmieren stark erleichtern.

Bei Steuerungsanwendungen (dazu gehören auch die meisten µC-Anwendungen)
ist zwar eine Strukturierung in Klassen möglich, meist stellt sich aber
heraus, dass von jeder Klasse nur maximal eine Instanz benötigt wird.
Solche Singletons kann man auch sehr gut in C realisieren, indem man je-
des in ein eigenes Programmmodul packt, wobei alle nur intern benötigten
Funktionen und globalen Variablen als static deklariert werden. Ob man
das so macht oder doch lieber C++ nimmt, ist dann eher Geschmackssache.

Die typischen 8-Bit-Controller sind meist so spärlich mit Flash und RAM
ausgestattet, dass darauf sowieso keine großen Programme Platz haben,
für die sich eine Klassenstruktur lohnen würde. Deswegen ist es mir
ziemlich egal, wie gut solche Plattformen von C++-Compilern unterstützt
werden.

Umgekehrt bieten embedded Plattformen, die für komplexere Software
geschaffen sind, ausreichend Ressourcen, um ohne nennenswerte Ein-
schränkungen auch C++ verwenden zu können.

von m.n. (Gast)


Lesenswert?

Das ist ja mal ne klare Ansage!

von Graphical User (Gast)


Lesenswert?

Hallo und vielen Dank für die zahlreichen Beiträge. "C++ in embedded 
systems: Myth and reality" werde ich lesen.

von Peter D. (peda)


Lesenswert?

Graphical User schrieb:
> "C++ in embedded
> systems: Myth and reality" werde ich lesen.

Scheint ja sehr einseitig zu sein:
"Anything C can do, C++ can do better"


Peter

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:
> Scheint ja sehr einseitig zu sein:
> "Anything C can do, C++ can do better"

Eher so: C++ umfasst C vollständig, auch syntaktisch, mit wenigen 
kleinen Unterschieden im Detail. Alles was C kann, kann also C++ 
mindestens genauso gut. Und manches geht in C++ eben besser.

von CS (Gast)


Lesenswert?

A. K. schrieb:
> Und manches geht in C++ besser.

Und wirklich gar nichts schlechter??
Wieso wurde dann reines C nicht schon lange abgeschafft??

Liegt es nur daran, dass viele Entwickler lieber C als C++ 
programmieren?

von (prx) A. K. (prx)


Lesenswert?

CS schrieb:
> Und wirklich gar nichts schlechter??

Wie sollte das möglich sein, wenn C++ (nahezu) eine Obermenge von C ist? 
Wenn also ein C Programm mit allenfalls kleinen Änderungen auch als C++ 
übersetzbar ist?

> Liegt es nur daran, dass viele Entwickler lieber C als C++
> programmieren?

Nicht jeder Entwickler mag C++.

Nicht jeder Entwickler kann C++.

Die meisten Entwicklungsumgebungen für Mikrocontroller können kein C++. 
Meist können sie es allenfalls dann, wenn drunter GCC werkelt.

von CS (Gast)


Lesenswert?

A. K. schrieb:
> Wie sollte das möglich sein, wenn C++ (nahezu) eine Obermenge von C ist?
> Wenn also ein C Programm mit allenfalls kleinen Änderungen auch als C++
> übersetzbar ist?

Das hoert sich hald so ein bisschen an wie "Jemand hat ein Auto 
entwickelt, dass alles kann was ein normales Auto auch kann, nur dass es 
kein Benzin braucht - trotzdem setzt es sich jahrelang nicht durch..."

Sorry, aber bin in C++ nicht so tief drin. Wenns so viel besser wäre, 
dann würden ja alle Hersteller einen C++-Compiler dazuliefern - schon 
aus Marketinggründen ("Schnellere Entwicklung", "mehr 
wiederverwendbar"...)

Oder lieg ich da falsch???

Gibt es eine g++ Version eigentlich für AVR/ARM? Wäre interessant mal 
damit ein wenig rumzuspielen bzw. Vergleichsprojekte zu machen...

Will keine Diskussion zu C vs C++, glaub das ist so sinnvoll wie über 
Betriebssysteme zu diskutieren...

von (prx) A. K. (prx)


Lesenswert?

CS schrieb:
> Oder lieg ich da falsch???

Ein leidlich fehlerarmer C++ Compiler ist ein ziemlich erkleckliches 
Stück Arbeit. Sehr viel komplexer als C. Das macht ein Hersteller nur, 
wenn er sich sicher ist, dass diese Arbeit nicht für die Katz ist.

Produkte setzten sich auch nicht automatisch durch, bloss weil sie 
besser sind. Sondern:
1
- Entwickler verwenden C, weil es für µC Enwicklung kein C++ gibt.
2
- Die µC-Hersteller bieten kein C++, weil die Entwickler C gewöhnt sind.
3
- Entwickler verwenden immer noch C, weil die Hersteller immer noch kein C++ bieten. Oder zu wenige.
4
- Die µC-Hersteller bieten immer noch kein C++, weil die Entwickler immer noch C brauchen.
5
  ...
Das haben wir schon immer so gemacht, da könnte ja jeder kommen. ;-)

von (prx) A. K. (prx)


Lesenswert?

CS schrieb:
> Gibt es eine g++ Version eigentlich für AVR/ARM? Wäre interessant mal
> damit ein wenig rumzuspielen bzw. Vergleichsprojekte zu machen...

Ich bin nicht mit den aktuellen AVR-Entwicklungsumgebungen von Atmel 
vertraut, nachdem Atmel da ja kräftig dran gedreht hat. Anno WinAVR war 
das jedenfalls dabei und problemlos möglich.

Diverse Entwicklungsumgebungen für ARM basieren auf GCC. Mindestens 
einige davon, wenn nicht vielleicht sogar alle, bieten daher auch C++.

von xfr (Gast)


Lesenswert?

Das Hauptfeature von C++ ist ja die objektorientierte Programmierung mit 
Klassen, Vererbung usw. Da das nur mit dynamischem Speicher ordentlich 
funktioniert, macht man das auf Mikrocontrollern in der Regel nicht.

Bleiben also "nur" die anderen, weniger bedeutenden Verbesserungen, mit 
denen man seinen Code besser strukturieren kann. Aber nur dafür lohnt es 
sich aus Herstellersicht nicht unbedingt, einen vollwertigen C++ 
Compiler zu entwickeln.

Ist vielleicht auch ein Henne-Ei-Problem. Man ist ja als professioneller 
Entwickler daran interessiert, möglichst wiederverwendbaren Code zu 
schreiben, der auf vielen Plattformen laufen kann. Da hat man mit reinem 
C mit Abstand die besten Chancen. Was hilft mir mein Projekt in 
wunderschönem, modularem C++, wenn ich meine Hardwareplattform umstellen 
möchte und es für den neuen Mikrocontroller keinen C++ Compiler gibt. 
Also bleibt man lieber bei C. Und weil alle bei C bleiben, sehen die 
Hersteller nicht die Notwendigkeit, einen C++ Compiler anzubieten ...

von (prx) A. K. (prx)


Lesenswert?

CS schrieb:
> Das hoert sich hald so ein bisschen an wie "Jemand hat ein Auto
> entwickelt, dass alles kann was ein normales Auto auch kann, nur dass es
> kein Benzin braucht - trotzdem setzt es sich jahrelang nicht durch..."

Könnte man so sagen. Denn diesas Auto wäre teurer als normale Autos 
mitsamt der voraussichtlichen Benzinkosten. Jedenfalls aus Sicht des 
Anbieters, der dafür viele viele Mannjahre Entwicklungsarbeit 
reinstecken müsste.

Bei grossen Eisen lohnt sich C++ schon lange. Deshalb existiert auch C++ 
in GCC - und nur als Nebeneffekt davon auch C++ für Microcontroller.

xfr schrieb:
> Ist vielleicht auch ein Henne-Ei-Problem

Ebendies spielt sicherlich eine wesentliche Rolle.

von Roland H. (batchman)


Lesenswert?

xfr schrieb:
> Das Hauptfeature von C++ ist ja die objektorientierte Programmierung mit
> Klassen, Vererbung usw. Da das nur mit dynamischem Speicher ordentlich
> funktioniert, macht man das auf Mikrocontrollern in der Regel nicht.

Es funktioniert auch statisch, und deshalb geht es wunderbar und 
problemlos auf µCs - bis runter in die 2k-Flash-Klasse.

CS schrieb:
> Gibt es eine g++ Version eigentlich für AVR/ARM? Wäre interessant mal
> damit ein wenig rumzuspielen bzw. Vergleichsprojekte zu machen...

GCC bietet C++ für AVR, ARM, MSP430, MIPS/PIC32, Renesas RX - vermutlich 
für alles, wofür ein backend für die Zielplattform vorhanden ist.

Vergleiche habe ich einige durchgeführt. Es gibt keinen Grund, C++ nicht 
einzusetzen. Die Mythen von "enormer Flash- und RAM-Bedarf" oder 
"riesiger Startup-Code" stimmen nicht.

A. K. schrieb:
> Ich bin nicht mit den aktuellen AVR-Entwicklungsumgebungen von Atmel
> vertraut, nachdem Atmel da ja kräftig dran gedreht hat. Anno WinAVR war
> das jedenfalls dabei und problemlos möglich.

Zu den IDEs kann ich auch nichts sagen, für die Kommandozeile 
funktioniert
http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORLINUX.aspx problemlos. 
Hinter der 3.4 (Atmel-Version) verbirgt sich GCC 4.6.2
1
$ avr-gcc --version
2
avr-gcc (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
3
Copyright (C) 2011 Free Software Foundation, Inc.
4
This is free software; see the source for copying conditions.  There is NO
5
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

xfr schrieb:
> Was hilft mir mein Projekt in
> wunderschönem, modularem C++, wenn ich meine Hardwareplattform umstellen
> möchte und es für den neuen Mikrocontroller keinen C++ Compiler gibt.

Welche neuen Mikrocontroller sind das, wofür es kein C++ oder GCC gibt? 
Ist es nicht eher genau anders, nämlich dass für neue Architekturen der 
Hersteller gleich auf GCC setzt, weil der Compilerbau ziemlich aufwändig 
ist?

Yalu X. schrieb:
> Ob ich etwas lieber in C oder in C++ schreibe, hängt fast ausschließlich
> von der Programmgröße ab. Alles, was maximal ein paartausend Zeilen lang
> ist, habe ich in C schneller hingeschrieben.

Wieso ist das in C schneller getippt?

Meine Erfahrung ist die, dass C++-Quelltexte kleiner sind :-)
Z. B. durch das implizite "this", Default-Werte für Funktionsparameter 
und templates.

Die andere Frage ist: Ab wann ist ein Programm groß, und würde man beim 
Erreichen dieser Grenze umstellen?

von Gerd E. (robberknight)


Lesenswert?

> Sorry, aber bin in C++ nicht so tief drin. Wenns so viel besser wäre,
> dann würden ja alle Hersteller einen C++-Compiler dazuliefern - schon
> aus Marketinggründen ("Schnellere Entwicklung", "mehr
> wiederverwendbar"...)

Welcher ernstzunehmende Hersteller hat denn 2012 noch kein C++?

von W.S. (Gast)


Lesenswert?

CS schrieb:
> Wieso wurde dann reines C nicht schon lange abgeschafft??

Ganz einfach:
Weil C++ deutlich komplizierter ist als C - oder nennen wir es 
'komplexer' (klingt besser).

Für Leute, die den ganzen Arbeitstag nix anderes machen als in C++ 
irgendwas zu programmieren, ist das alles kein Thema. Die haben nämlich 
keine anderen Probleme, die ihnen im Kopf herumkollern.

Aber für Leute, die eben nicht nur 100% in C++ programmieren, sondern 
z.B. auch Schaltungen entwickeln, Leiterplatten layouten, Gehäuse 
konstruieren, mit Zulieferern herumfeilschen und ihren Kunden 
Telefonseelsorge angedeihen lassen müssen, ist C++ schlichtweg 
unbrauchbar, weil nicht zu merken. Ich merk sowas ja an mir selber, daß 
ich versehentlich mal nen Pascal-Ausdruck in ne C-Quelle tippe oder nen 
C-Ausdruck in Verilog oder umgekehrt. Man braucht ne Weile, um mental 
umzupolen und bei C++ ist diese Weile viel zu lang.

Ich sehe die ganz gleiche Diskussion bei Leiterplattenleuten und 
Konstrukteuren, wo manche auf besonders mächtige Tools schwören, dabei 
aber vergessen, daß man selbige tagtäglich benutzen muß, um drin zu 
bleiben. Früher hatte ich mal ganz flüssig mit Autocad konstruieren 
können, heute muß ich erstmal nachgrübeln 'wie war das doch gleich mit 
...'

Kurzum, sowas wie C++ geht in größeren Firmen, wo jeder seine 
Monokultur/Spezialisierung betreiben kann. In kleineren Firmen - dem 
sogenannten Mittelstand - geht es schwer oder garnicht, weil es da keine 
ausreichend weit gehende Arbeitsteilung gibt und man als Ingenieur viel 
mehr Probleme hat als bloß die Programmierung - und weil nur die 
Wenigsten nen Kopf haben wie ein Elefant.

W.S.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Roland H. schrieb:
> Yalu X. schrieb:
>> Ob ich etwas lieber in C oder in C++ schreibe, hängt fast ausschließlich
>> von der Programmgröße ab. Alles, was maximal ein paartausend Zeilen lang
>> ist, habe ich in C schneller hingeschrieben.
>
> Wieso ist das in C schneller getippt?

Wenn man alle Funktionen als Methoden in Klassen packt, muss man jeden
Methodenkopf doppelt schreiben, einmal in der Klassendeklaration und
einmal in der Methodendefinition. In C gilt dies nur für diejenigen
Funktionen, die über Modulgrenzen hinweg verwendet werden, also
praktisch "public" sind. Jede Änderung der Methodenparameter muss man
ebenfalls an zwei Stellen vornehmen. Hinzu kommt der Rahmen der
Klassendeklaration selbst (also class { public: ... private: ...}). Bis
zu einem gewissen Grad nimmt einem ein leistungsfähiger Editor oder eine
IDE diese Arbeit ab. Trotzdem habe ich in C++ immer das Gefühl, einen
Großteil der Zeit redundanten Code zu tippen.

> Meine Erfahrung ist die, dass C++-Quelltexte kleiner sind :-)

Das sind sie auch, sobald man Dinge wie die STL nutzen kann/darf, aber
eben nur dann.

A. K. schrieb:
> Produkte setzten sich auch nicht automatisch durch, bloss weil sie
> besser sind. Sondern:
> - Entwickler verwenden C, weil es für µC Enwicklung kein C++ gibt.
> - Die µC-Hersteller bieten kein C++, weil die Entwickler C gewöhnt
>   sind.
> - Entwickler verwenden immer noch C, weil die Hersteller immer noch
>   kein C++ bieten. Oder zu wenige.
> - Die µC-Hersteller bieten immer noch kein C++, weil die Entwickler
>   immer noch C brauchen. ...

Oft würden die Entwickler gerne C++ verwenden, aber der Chef oder die
Firmenphilosophie schreiben C vor.

von Simon B. (nomis)


Lesenswert?

Nur um nochmal ein Statement in die Diskussion einzubringen, das 
unabhängig von dem Prozessortyp oder anderen Randbedingungen ist:

C++ ist ein schlecht gestaltetes Amalgam aus verschiedenen 
Programmiersprachenkonzepten, das mit Gewalt in eine C-artige 
Erscheinungsform gepresst wurden.

Natürlich ist das bewusst zugespitzt formuliert, natürlich wird das 
Widerspruch von den Leuten hervorrufen, die C++ tagtäglich freiwillig 
verwenden. Aber C++ leidet an einer unglaublich überladenen (im 
mehrfachen Wortsinne) Syntax und hat die Chance vertan, bei der 
Gelegenheit mal mit dem Ballast von C aufzuräumen.

Ich habe viel Spaß gehabt, als ich mir die C++ FQA ("frequently 
questioned answers", http://yosefk.com/c++fqa/ ) durchgelesen habe. In 
der arbeitet sich der Autor an der C++ FAQ ab, deren Antworten er 
paraphrasiert und dann im Detail ausführt, warum die Antwort 
falsch/unvollständig ist oder die Probleme von C++ schönfärbt/ignoriert.

Das ist natürlich auch ein hochgradig subjektives Dokument, über das 
sich auch an einigen Stellen diskutieren lässt, vielleicht an manchen 
Stellen auch überholt ist. Aber es hat dennoch viele interessante Punkte 
und ist generell spaßig zu lesen, wenn man sich für die Details von 
Programmiersprachen interessiert. Eigentlich sollte sich jeder mal 
http://yosefk.com/c++fqa/defective.html durchlesen. Selbst wenn man 
nicht der Meinung des Autors ist gewinnt man doch mal eine Einsicht, 
welche Kriterien man an Programmiersprachen anlegen kann.

Viele Grüße,
        Simon

von debugger (Gast)


Lesenswert?

Roland H. schrieb:
> xfr schrieb:
>> Das Hauptfeature von C++ ist ja die objektorientierte Programmierung mit
>> Klassen, Vererbung usw. Da das nur mit dynamischem Speicher ordentlich
>> funktioniert, macht man das auf Mikrocontrollern in der Regel nicht.
>
> Es funktioniert auch statisch, und deshalb geht es wunderbar und
> problemlos auf µCs - bis runter in die 2k-Flash-Klasse.

Das ist es eben, ich programiere schon seid vielen Jahren in C++ 
verwende wie selbstverständlich z.B. templates der STL für deren 
Verwendung immer dyn. Speicher von einer heap-verwaltung alloziieren 
wird. Wie kann ich  dies an einen statischen Speicher binden?

> W.S. schrieb:
> Für Leute, die den ganzen Arbeitstag nix anderes machen als in C++
> irgendwas zu programmieren, ist das alles kein Thema. Die haben nämlich
> keine anderen Probleme, die ihnen im Kopf herumkollern.

So ganz stimmt deine Argumentation nicht, die Verwendung von C++ futures 
ist fliessend möglich. Die verwednung des C++ synt. kann ja auch nur 
teilweise erfolgen, z.Z. nur Klassen anstatt struct Definitionen. 
Deshalb muss ich kein C++ freak sein und meine Kenntnisse entwicken sich 
schrittweise.

> W.S. schrieb:
> Kurzum, sowas wie C++ geht in größeren Firmen, wo jeder seine
> Monokultur/Spezialisierung betreiben kann. In kleineren Firmen - dem
> sogenannten Mittelstand - geht es schwer oder garnicht, weil es da keine
> ausreichend weit gehende Arbeitsteilung gibt und man als Ingenieur viel
> mehr Probleme hat als bloß die Programmierung - und weil nur die
> Wenigsten nen Kopf haben wie ein Elefant.

Gerade in einer kleineren Firmen ist deren verwendung ein entscheidener 
Vorteil für das Produkt, wenn es, wie z.B. in meinen Fall, über viele 
Jahre entwickelt und gepflegt werden muss. Ach ja und ich telefoniere 
zwischen durch auch schon mal mit einigen Kunden...

> Oft würden die Entwickler gerne C++ verwenden, aber der Chef oder die
> Firmenphilosophie schreiben C vor.

Ein ziemliches Armutszeugniss und die sichtweise des Management reicht 
nur wochenweise bis zum Projektabschluss, Lieferung... push, money and 
forget
oder der chef hat keine Ahnung... Mein chef ist Entwickler :-)

von (prx) A. K. (prx)


Lesenswert?

Simon Budig schrieb:
> C++ ist ein schlecht gestaltetes Amalgam aus verschiedenen
> Programmiersprachenkonzepten, das mit Gewalt in eine C-artige
> Erscheinungsform gepresst wurden.

Völlig richtig. Mir standen stellenweise die Haare zu Berge als ich den 
Stroustrup las. Der hat auf die syntaktischen Fehler von C noch weitere 
drauf gesetzt, statt sie gerade zu ziehen.

Aber der Versuch des Pentagon, Ada durchzusetzen, ist an der Realität 
gescheitert. Man hat faktisch eben nur C oder C++ zur Auswahl. Der Rest 
spielt im Zusammenhang mit Microcontrollern keine nennenswerte Rolle.

von Roland H. (batchman)


Lesenswert?

Yalu X. schrieb:
> Wenn man alle Funktionen als Methoden in Klassen packt, muss man jeden
> Methodenkopf doppelt schreiben, einmal in der Klassendeklaration und
> einmal in der Methodendefinition.

Nicht immer, es gilt nicht für die inline-Variante. Bei "public" ist der 
Aufwand in C/C++ der gleiche, ebenso, wenn es einer forward-Deklaration 
bedarf. Bleiben also non-inline private Methoden. OK.

Dem steht die Verwendung von "this" gegenüber, und das spart eine ganze 
Menge Tipperei. Durch den Klassennamen spart man sich auch ggf. einen 
Präfix für den Funktionsnamen, damit die Namen eindeutig sind.

> Hinzu kommt der Rahmen der
> Klassendeklaration selbst (also class { public: ... private: ...}).

"private" ist der Default, dass müsste man nicht unbedingt eintippen. 
Und wie würde man den Sachverhalt "private/interne Variable in einem 
struct" in C darstellen? Das muss auch irgendwie dokumentiert werden.

>> Meine Erfahrung ist die, dass C++-Quelltexte kleiner sind :-)
>
> Das sind sie auch, sobald man Dinge wie die STL nutzen kann/darf, aber
> eben nur dann.

Wenn man ein ein C++-Feature nicht nutzen darf, dann wird das 
"C-Äquivalent im C++-Quelltext" auch nicht länger.

Selbst wenn man reines C mit einem C++-Compiler verwendet, ergeben sich 
Vorteile: Zusätzliche Warnings, typsichere enums.

Yalu X. schrieb:
> Oft würden die Entwickler gerne C++ verwenden, aber der Chef oder die
> Firmenphilosophie schreiben C vor.

Ja, das erlebe ich leider immer wieder: Wenn es irgendwelche Regularien 
gibt oder es organisatorisch nicht passt oder nicht gewollt ist. Das ist 
allerdings eine andere Diskussion; technisch würde ich sagen, dass 
nichts gegen C++ spricht.

von (prx) A. K. (prx)


Lesenswert?

Roland H. schrieb:
> Dem steht die Verwendung von "this" gegenüber, und das spart eine ganze
> Menge Tipperei.

Ich habe nicht den Eindruck, dass beim Programmieren wirklich die 
Tipparbeit im Vordergrund steht. Allerdings weiss ich natürlich nicht, 
wie langsam ihr tippt. ;-)

Yalu X. schrieb:
> Wenn man alle Funktionen als Methoden in Klassen packt, muss man jeden
> Methodenkopf doppelt schreiben, einmal in der Klassendeklaration und
> einmal in der Methodendefinition.

Also ob das im copy-and-paste Zeitalter viel Arbeit darstellte.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Simon Budig schrieb:
> C++ ist ein schlecht gestaltetes Amalgam aus verschiedenen
> Programmiersprachenkonzepten, das mit Gewalt in eine C-artige
> Erscheinungsform gepresst wurden.

Damit hast du nicht ganz unrecht, aber diese "Amalgame" (zu denen auch
Java, Objective-C und C# gehören), sind die Mainstream-Programmier-
sprachen. Im Tiobe-Index belegen sie zusammen einen Anteil von über 40%,
zusammen mit ihrem gemeinsamen Vorfahr C sind es sogar über 60%. Wegen
der steigenden Popularität von Objective-C (iPhone-Effekt) zeigt die
Tendenz sogar nach oben.

A. K. schrieb:
> Ich habe nicht den Eindruck, dass beim Programmieren wirklich die
> Tipparbeit im Vordergrund steht.

Objektiv gesehen nicht, aber mitunter subjektiv :)

> Allerdings weiss ich natürlich nicht, wie langsam ihr tippt. ;-)

Seeehr langsam ;-)

> Also ob das im copy-and-paste Zeitalter viel Arbeit darstellte.

So sehr viel vielleicht nicht, aber:

- Ein gewisser Zusatzaufwand ist trotzdem vorhanden, zumal die Sache mit
  dem Copy/Paste einer Zeile ja noch nicht ganz getan ist.

- Es ist eine dieser "niederen" Tätigkeiten, die insbesondere dann für
  Unmut sorgt, wenn die Zeit gerade knapp ist.

- Denken macht einfach mehr Spaß als Tippen.

- Die Alternativen stehen ja bereit und warten nur darauf, genutzt zu
  werden. Und das mache ich dann eben, wenn keine anderen triftigen
  Gründe dagegen sprechen.

von Simon B. (nomis)


Lesenswert?

Yalu X. schrieb:
> Damit hast du nicht ganz unrecht, aber diese "Amalgame" (zu denen auch
> Java, Objective-C und C# gehören), sind die Mainstream-Programmier-
> sprachen.

Ja, populär ist C++ ohne jeden Zweifel. C++ gehört sicher zu den 
Sprachen mit denen man halbwegs klarkommen sollte, wenn man in der Wahl 
seiner Werkzeige nicht 95%ig frei ist...  :)

Ich würde aber C++ nicht in einen Topf mit Java und C# werfen wollen. 
Meine Erfahrung mit Java sind sehr begrenzt, mit C# nicht vorhanden. 
Aber trotzdem haben sie nur eine oberflächliche syntaktische Ähnlichkeit 
mit C++. Was meines Wissens sowohl Java als auch C# qualitativ deutlich 
von C++ abhebt ist, dass sie ein sauberes Objektmodell haben (was bis 
auf die Ebene der VM hinuntergeht). Sie haben sich soweit von den 
Strukturen von C gelöst, dass sie eben nicht mehr noch mit Krampf 
"kompatibel" zu C sind. Da hat sich jemand hingesetzt und sorgfältig 
drüber nachgedacht, was man (noch) braucht, was man über Bord wirft und 
was man neu erfinden muss.

C# gehört - trotz meiner Animositäten gegenüber Microsoft - definitiv zu 
den Sachen die ich mir ansehen will, auch weil ich von Leuten deren 
Kompetenz ich sehr achte gehört habe, dass es gegenüber Java die 
sauberere Sprache sein soll.

Bei C++ hat Stroustroup C hergenommen und geguckt wie man da Objekte 
reinbauen kann. Objekte sind wie structs, aber das darf man ja nicht 
laut sagen, also nehmen wir "class" - sonst sieht das ja nicht neu aus. 
Oh, und wir müssen Operatoren überladen können, also nehmen wir mal 
"operator++()" her. Oh, da gibt es ja noch die Postfix-Variante, da 
nehmen wir dann "operator++(int)" mit einem ungenutzten Dummy-Argument 
(WTF?). Und in einer anderen Sprache habe ich mal auf Textersetzung 
basierende Programmierung gesehen, da erfinde ich jetzt mal Templates 
mit einer komplett von C abgekoppelten Infrastruktur. Oh, und der 
Shift-Operator sieht grafisch so ähnlich aus wie Richtungspfeile, das 
können wir gut für IO-Operationen verwenden...

Oh, und damit wir niemand verschrecken behalten wir C als Subset. Und 
wenn es in Details dann eben doch nicht kompatibel ist dann ignorieren 
wir das Problem.

Verdammt, es wird ein Rant...  :)

C++ wurde entwickelt indem man C hergenommen hat und dann rangeflanscht 
hat ohne mal einen Schritt zurückzutreten und sich das Resultat als 
ganzes mal anzugucken. Bei Java und C# war mehr Sorgfalt am Werk.

> Im Tiobe-Index belegen sie zusammen einen Anteil von über 40%,
> zusammen mit ihrem gemeinsamen Vorfahr C sind es sogar über 60%. Wegen
> der steigenden Popularität von Objective-C (iPhone-Effekt) zeigt die
> Tendenz sogar nach oben.

Ja, unbestritten. Auch PHP hat Syntaxelemente die ähnlich wie C 
aussehen. Auch PHP wird von vielen tausenden Leuten eingesetzt. Und in 
der Tat ist PHP noch dramatisch viel schlechter als C++...

Für mich ist die Ästhetik von Programmiersprachen wichtig. Sicherlich 
spielt dabei eine Rolle, dass ich als Mathematiker klare Strukturen 
suche und ein "Hauptsache es funktioniert" nicht reicht damit ich mich 
wohlfühle. Aber meistens komme ich damit klar, wenn ich gelegentlich 
einen Rant loslassen kann...   :)

Viele Grüße,
        Simon

von Wusel D. (stefanfrings_de)


Lesenswert?

Ich bin nicht sicher, ob Graphical User (Gast) auch die ganz kleinen 
Mikrocontroller im Sinn hat. Jedenfalls gibt es einige, die keinen Stack 
haben. Sie können in C eingeschränkt programmiert werden, C++ geht 
darauf aber gar nicht.

Ich habe schonmal einen Mikrocontroller mit 2KB Ram in C++ programmiert, 
dabei allerdings viel mit statischen Objekt-Instanzen gearbeitet. Alle 
anderen Mikrocontroller-Projekte habe ich allerdings in Assembler oder C 
programmiert.

Ich hatte nicht das Gefühl, dass C++ mir in diesem Projekt signifikante 
Vorteile gebracht hat. Es war daher bei einem einmaligen Versuch 
geblieben.

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.