Forum: PC-Programmierung Literatur C++ für C-Programmierer bzw. C++ Internals


von Jonas S. (microwave)


Lesenswert?

Hi Community!

- Welche engl. oder deutsche Literatur könnt ihr empfehlen zum Umstieg 
von C auf C++?
Dies können Bücher (engl., deutsch), Websites oder PDFs sein.
Anwendungsgebiet ist die Entwicklung von Software auf der Kommandozeile 
in Linux oder Windows.
Bisher habe ich das Buch und den gleichnamigen Kurs von Ira Pohl 
gefunden. Meinungen?
Das Kursmaterial https://www.coursera.org/learn/c-plus-plus-a ist 
irgendwie nicht zu erhalten, obwohl sie es schreiben.

- Erwünscht ist (zudem) die Diskussion auf Assembler-Ebene der 
grundlegenden Features (Konstruktoren, Referenzen, "new/delete", Klassen 
und Vererbung, evtl. exceptions, etc.).
Oder: Mit welchen Features verlässt man den Compiler-Bereich und es wird 
Assembler-Code erzeugt, der sich von C unterscheidet? Ich denke, 
einfache Klassen an sich provozieren keinen (oder minim) 
unterschiedlichen Code gegenüber C-structs?
Bestenfalls sollte in der Diskussion bzw. Analyse der 
x86/x86-64-Befehlssatz in Intel-Syntax (!) verwendet worden sein.
Falls es im Mikrocontroller-Bereich derartige Literatur gibt, darf nur 
der AVR 8-bit-Befehlssatz referenziert werden.

Freundliche Grüsse

Microwave89

: Verschoben durch User
von Rolf M. (rmagnus)


Lesenswert?

Zur Sprache selbst würde ich The C++ Programming Language vom Erfinder 
der Sprache empfehlen. Gibt's auch auf Deutsch, aber ich weiß nicht, ob 
das was taugt.

Jonas S. schrieb:
> - Erwünscht ist (zudem) die Diskussion auf Assembler-Ebene der
> grundlegenden Features (Konstruktoren, Referenzen, "new/delete", Klassen
> und Vererbung, evtl. exceptions, etc.).

Wie das implementiert ist, ist compiler- und plattformspezifisch. Warum 
glaubst du, dass das für das Erlernen der Sprache wichtig ist?

> Oder: Mit welchen Features verlässt man den Compiler-Bereich und es wird
> Assembler-Code erzeugt, der sich von C unterscheidet?

Was meinst du "verlässt man den Compiler-Bereich"? C und C++ sind 
verschiedene Sprachen, natürlich generieren die Compiler 
unterschiedlichen Code. Dadurch verlässt man aber nicht irgendeinen 
Bereich.

> Ich denke, einfache Klassen an sich provozieren keinen (oder minim)
> unterschiedlichen Code gegenüber C-structs?

Das hängt davon ab, was "einfache Klassen an sich" sein sollen. Wenn du 
PODs meinst, dann hast du wahrscheinlich recht. Sobald aber 
Konstruktoren, Vererbung, Polymorphie u.s.w. dazukommen, sieht's ganz 
anders aus.

von Raoul D. (raoul_d219)


Lesenswert?

Jonas S. schrieb:
> Hi Community!
>
> - Welche engl. oder deutsche Literatur könnt ihr empfehlen zum Umstieg
> von C auf C++?
> Dies können Bücher (engl., deutsch), Websites oder PDFs sein.
> Anwendungsgebiet ist die Entwicklung von Software auf der Kommandozeile
> in Linux oder Windows.

Wie wäre es damit:

http://mozart.informatik.fh-kl.de/download/Lehre/WS1617/Prog2/Vorlesung/doc/ppcP9000.html

von Jonas S. (microwave)


Lesenswert?

Allgemein: Danke für die schnellen Antworten, komme erst jetzt dazu, zu 
antworten.

Rolf M. schrieb:
> Warum
> glaubst du, dass das für das Erlernen der Sprache wichtig ist?

Es hilft mir beim Erlernen und korrekten Anwenden, wenn ich verstehe, 
wie ich mir x und y auf C- bzw. Assembler-Ebene vorstellen muss. 
Ausserdem möchte ich immer gerne verstehen, wie etwas unter der Haube 
funktioniert.

Rolf M. schrieb:
> Was meinst du "verlässt man den Compiler-Bereich"?

Also welche Features erzeugen von C deutlich verschiedenen 
Maschinencode?
Eben - Bei einer einfachen Klasse (ich weiss gerade (noch) nicht, was 
POD ist) mit Gettern und Settern aber ohne Kon-/Destruktoren kann ich 
mir vorstellen, dass grundsätzlich ähnlicher Code erzeugt wird wie für 
ein C-struct mit u.a. Funktionszeigern darin. "new" und "delete" 
allozieren intern irgendwo/-wie Speicher, z.B. mit malloc.
Bei Konstruktoren bzw. Destruktoren wird eine C-ähnliche Entsprechung in 
Assembler/Maschinencode schon schwierig. Für mich wäre das wie eine 
Funktion, die sich nicht an eine Standard-ABI hält, weil es da ja nicht 
mal ein "void" als Rückgabe gibt.
Und dann richtig schwer - wie muss ich mir z.B. die &-Referenzen 
vorstellen?
Ich kenne nur
1
void foo(int bar){}
2
void foo2(int* bar){}
3
...
4
foo(789);
5
foo(&blah);
, was ich mir zumindest in x86(-64)-Assembler gut vorstellen kann.
Wie soll jedoch
1
void foo(int &bar){}
in Assembler aussehen? Ich kann die Funktion noch nicht einmal auswendig 
aufrufen... :/

Ihr "müsst" die Fragen nicht ohne Not beantworten, sie sollen aber die 
Richtung zeigen, in die ich stutzig werde und Literaturtipps wünsche.

Rolf M. schrieb:
> Sobald aber
> Konstruktoren, Vererbung, Polymorphie u.s.w. dazukommen, sieht's ganz
> anders aus.

Exakt dies dachte ich. Wahrscheinlich ist die beste Lösung erstmal, den 
Output des Compilers (und Linkers) bei einem einfachen aber klar 
objektorientierten Programm zu disassemblieren.

Raoul D. schrieb:
> Wie wäre es damit:
>
> 
http://mozart.informatik.fh-kl.de/download/Lehre/WS1617/Prog2/Vorlesung/doc/ppcP9000.html

Habe nicht wirklich hineingeschaut, aber da steht eher etwas von 
Java-Umstieg, und das ist bei mir schon länger her... ;)

Grüsse - Microwave

von Herbert P. (Gast)


Lesenswert?

Die Seite könnte helfen: https://gcc.godbolt.org/

Gruß Herby

von Wilhelm M. (wimalopaan)


Lesenswert?

Wenn Du C++ lernen möchtest, dann möchtest Du offensichtlich klassisch 
OOP lernen oder generische Programmierung - irgendetwas anderes 
besonderes an C++? Prozedural kannst Du ja schon, weil Du von C kommst.
Daher würde ich mich auch damit beschäftigen, und die 
Assembler-Umsetzung (zunächst) ausser acht lassen. Erst wenn Du das 
verstanden hast, dann gehe an die Details ...

von Chris F. (chfreund) Benutzerseite


Lesenswert?

Guck Dir mal den "C++ Primer" an. Das ist ein gutes, allgemeines Buch. 
Aktuell ist die fünfte Auflage und es gibt das in Deutsch und Englisch.

von Nase (Gast)


Lesenswert?

Jonas S. schrieb:
> Rolf M. schrieb:
>> Warum
>> glaubst du, dass das für das Erlernen der Sprache wichtig ist?
>
> Es hilft mir beim Erlernen und korrekten Anwenden, wenn ich verstehe,
> wie ich mir x und y auf C- bzw. Assembler-Ebene vorstellen muss.
Das hilft nicht, vergess es einfach ganz schnell. Ich unterstelle dir 
jetzt einfach (nicht böse gemeint, sondern realistisch), dass du 
(genauso wie selbst die meisten professionellen Programmierer) schon den 
Befehlssatz einer einigermaßen aktuellen CPU nicht mehr sinnstiftend 
verstehen.
Du möchtest mit C++ eine sehr leistungsfähige Programmiersprache lernen. 
Dafür gibts sehr gute Compiler, die mehr von Assembler verstehen, als du 
:-)

Was hilft: Mach dir klar, wo und wie Code erzeugt wird.


> Ausserdem möchte ich immer gerne verstehen, wie etwas unter der Haube
> funktioniert.
Das wiederum ist ja legitim. Aber dazu brauchts kein Assembler.

>
> Rolf M. schrieb:
>> Was meinst du "verlässt man den Compiler-Bereich"?
>
> Also welche Features erzeugen von C deutlich verschiedenen
> Maschinencode?
> Eben - Bei einer einfachen Klasse (ich weiss gerade (noch) nicht, was
> POD ist)
Plain-old-data. Im Prinzip das, was eine struct in C ist/war.

> mit Gettern und Settern
C++ kenn keine Getter und Setter.

> aber ohne Kon-/Destruktoren kann ich
> mir vorstellen, dass grundsätzlich ähnlicher Code erzeugt wird wie für
> ein C-struct mit u.a. Funktionszeigern darin.
Nein, wozu auch?
Bei einer einfachen Klasse gibt es nicht die geringste Notwendigkeit für 
Funktionszeiger. Der Compiler wird nach wie vor einfache Funktionen 
erzeugen, die dann vom Linker zur Compilezeit fest zusammengebunden 
werden. Fertig. Wenn du magst, stell dir vor, dass diese Funktionen als 
unsichtbares Argument immer den "this"-Zeiger haben.

Der Vergleich mit der C-Struktur mit Zeigern drin ist schwierig. In C 
ist das eine Krücke, weil man quasi die "Methoden" zum "Objekt" packen 
möchte. In C++ macht das im Normalfall nach wie vor der Linker zur 
Compilezeit.

Erst bei Vererbung von Klassen kann man in C++ fordern, dass 
Funktionen eben nicht zur Compilezeit gebunden werden, sondern erst zur 
Laufzeit. Das nennt man dort "virtuelle Methode". Und für solche wird 
dann tatsächlich eine kleine Struktur mit Funktionszeigern angelegt, die 
sich gemeinhin "vtable" nennt.

> "new" und "delete"
> allozieren intern irgendwo/-wie Speicher, z.B. mit malloc.
Ja, die haben i.d.R. sogar irgendwo eine Implementierung.

> Bei Konstruktoren bzw. Destruktoren wird eine C-ähnliche Entsprechung in
> Assembler/Maschinencode schon schwierig. Für mich wäre das wie eine
> Funktion, die sich nicht an eine Standard-ABI hält, weil es da ja nicht
> mal ein "void" als Rückgabe gibt.
Warum? Der Konstruktor ist einfach nur eine Funktion mit "void als 
Rückgabe", wie du es schreibst. Auch diese Funktion kriegt, wenn du so 
magst, als erstes Argument "this" übergeben und soll dann zusehen, wie 
sie "this" sinnvoll initialisiert. Der Speicher, auf den "this" zeigt, 
wurde zuvor ja schon vom new-Operator angefordert.

> Und dann richtig schwer - wie muss ich mir z.B. die &-Referenzen
> vorstellen?
> Ich kenne nurvoid foo(int bar){}
> void foo2(int* bar){}
> ...
> foo(789);
> foo(&blah);, was ich mir zumindest in x86(-64)-Assembler gut vorstellen
> kann.
> Wie soll jedochvoid foo(int &bar){}in Assembler aussehen? Ich kann die
> Funktion noch nicht einmal auswendig
> aufrufen... :/
Warum nicht?
Es ist völlig wurscht, wie der Compiler eine Referenz übersetzt. Eine 
Referenz ist nur ein zweiter Name für ein Objekt. In vielen Fällen 
könntest du das sogar durch ein prähistorisches Präprozessormakro 
(#define) ersetzen.


> Rolf M. schrieb:
>> Sobald aber
>> Konstruktoren, Vererbung, Polymorphie u.s.w. dazukommen, sieht's ganz
>> anders aus.
>
> Exakt dies dachte ich. Wahrscheinlich ist die beste Lösung erstmal, den
> Output des Compilers (und Linkers) bei einem einfachen aber klar
> objektorientierten Programm zu disassemblieren.
Das ist eine ziemlich absurde Idee.

Welchen Erkenntnisgewinn versprichst du dir denn davon? Ich meine, du 
kannst ja gerne dem Optimierer beim Arbeiten zugucken und wirst alsbald 
feststellen, dass der Optimierungen kennt und anwendet, die du auch nach 
drei Flaschen Lambrusco noch nicht nachvollziehen kannst :-)
Du wirst feststellen, dass der Linker immer noch genauso linkt, wie 
früher. Nur die Namen der Funktionen sehen etwas anders aus, weil wegen 
der Überladungen noch eine Signatur dazukommt. Das passiert unter dem 
Arbeitstitel "name mangling".

Les doch einfach mal Wikipedia-Artikel zu einigen Stichworten in meiner 
Antwort. Wenn du ja schon Hintergrund in C hast, sollte das dir einen 
Überblick verschaffen.

von Rolf M. (rmagnus)


Lesenswert?

Jonas S. schrieb:
> Allgemein: Danke für die schnellen Antworten, komme erst jetzt dazu, zu
> antworten.
>
> Rolf M. schrieb:
>> Warum
>> glaubst du, dass das für das Erlernen der Sprache wichtig ist?
>
> Es hilft mir beim Erlernen und korrekten Anwenden, wenn ich verstehe,
> wie ich mir x und y auf C- bzw. Assembler-Ebene vorstellen muss.
> Ausserdem möchte ich immer gerne verstehen, wie etwas unter der Haube
> funktioniert.

Die Idee einer Hochsprache ist aber gerade, dass man das nicht braucht. 
Ich würde dir empfehlen, dich erstmal nur auf der C++-Ebene zu bewegen, 
und wenn du verstanden hast, wie die Sprache funktioniert und zwecks 
Optimierung genauer bescheid wissen willst, dann tu das danach.
Das Problem wird auch sein, dass du die modernen aggressiven Optimizer 
das, was generiert wird, für Menschen recht schwer verständlich wird. 
Und schaltet man den Optimizer aus, hat man keine realistische 
Einschätzung mehr.

> Rolf M. schrieb:
>> Was meinst du "verlässt man den Compiler-Bereich"?
>
> Also welche Features erzeugen von C deutlich verschiedenen
> Maschinencode?

Wie gesagt: Das hängt sehr vom Compiler ab, auch wenn es einige 
"gängige" Implementationen gibt. Früher(tm) haben C++-Compiler C-Code 
generiert. Heute erzeugen sie aber in der Regel direkt Assembler-Code, 
weil das besseres Optimierungspotenzial bietet. Ich glaube Comeau C++ 
kann noch nach C konvertieren, kostet aber was und ist anscheinend seit 
2013 nicht mehr sonderlich aktiv.

> Eben - Bei einer einfachen Klasse (ich weiss gerade (noch) nicht, was
> POD ist)

"plain old data", also etwas, das im Prinzip genauso wie eine C-Struktur 
aufgebaut ist. Bekommt man, wenn die Klasse keine Kontruktoren und 
keinen Destruktor hat, keine Basisklassen, keine Member-Variablen, die 
selbst nicht POD sind und keine virtuellen Memberfunktionen.

> mit Gettern und Settern aber ohne Kon-/Destruktoren kann ich
> mir vorstellen, dass grundsätzlich ähnlicher Code erzeugt wird wie für
> ein C-struct mit u.a. Funktionszeigern darin.

Nein, Funktionszeiger werden da nicht angelegt. Nur die Variablen sind 
enthalte und bei virtuellen Memberfunktionen ein oder mehrere 
Vtable-Zeiger.

> "new" und "delete" allozieren intern irgendwo/-wie Speicher, z.B. mit
> malloc.

Ja, allerdings wirft new eine Exception, wenn kein Speicher mehr da ist.

> Bei Konstruktoren bzw. Destruktoren wird eine C-ähnliche Entsprechung in
> Assembler/Maschinencode schon schwierig. Für mich wäre das wie eine
> Funktion, die sich nicht an eine Standard-ABI hält, weil es da ja nicht
> mal ein "void" als Rückgabe gibt.

Da wird noch einiges außenrum gemacht. Schließlich müssen auch die 
Konstruktoren / Destruktoren der Basisklassen und Membervariablen 
aufgerufen und verschiedene weitere Initialisierungen gemacht werden.

> Und dann richtig schwer - wie muss ich mir z.B. die &-Referenzen
> vorstellen?

Die sind das einfachste. Die Compiler, die ich kenne, implementieren das 
unter der Haube einfach genau wie Zeiger.

> Rolf M. schrieb:
>> Sobald aber
>> Konstruktoren, Vererbung, Polymorphie u.s.w. dazukommen, sieht's ganz
>> anders aus.
>
> Exakt dies dachte ich. Wahrscheinlich ist die beste Lösung erstmal, den
> Output des Compilers (und Linkers) bei einem einfachen aber klar
> objektorientierten Programm zu disassemblieren.

Wie gesagt: Ich halte es für wenig sinnvoll, so vorzugehen. C++ selbst 
ist schon schwierig genug, da muss man sich nicht zusätzlich auch noch 
aufhalsen, den erzeugten Code verstehen zu wollen.

von H-G S. (haenschen)


Lesenswert?

Die "Für Dummies"-Bücher sind immer gut  :-)

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.