kostenloser Webspace werbefrei: lima-city


C oder C++ lernen?

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    bastians-seite

    Kostenloser Webspace von bastians-seite

    bastians-seite hat kostenlosen Webspace.

    Was lohnt sich am meisten zu lernen? Ich hab angefangen mit C, aber bin nachdenklich geworden, on C++ nicht die

    bessere Wahl wäre. Was denkt ihr? Ich finde sonst eigentlich C leichter,

    wenn jemand mir C++ empfhielt, gibts dazu noch ein gutes Buch, hab nur gute C-Bücher gefunden?
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. C ist vollständig -- also mit allen Warzen und Mis-features -- in C++ enthalten. Wenn Du also C kannst, ist C++ eine "Erweiterung". Erst C zu lernen und dann C++ ist sicherlich der beste Weg, allerdings werden dann die meisten Lehrbücher für C++ in den ersten zwei oder drei Kapiteln zu reinen Wiederholungen.
  4. kommt imho darauf an was du machen willst.
    C macht Sinn in maschienennahen oder Hochperformanceprogrammen.
    C++ ist dahingegen moderner und damit mehr gerneral purpose.

    Die c++ syntax ist umfangreicher, empfinde ich damit aber als leichter, da moderne Programmierkonzepte angewendet werden können und so zum Beispiel weniger Codeduplizierung oder Aufwand der Speicherveraltung von Nöten ist.


    Beitrag zuletzt geändert: 14.11.2015 21:45:35 von thecity
  5. hddg schrieb:
    C ist vollständig -- also mit allen Warzen und Mis-features -- in C++ enthalten. Wenn Du also C kannst, ist C++ eine "Erweiterung". Erst C zu lernen und dann C++ ist sicherlich der beste Weg, allerdings werden dann die meisten Lehrbücher für C++ in den ersten zwei oder drei Kapiteln zu reinen Wiederholungen.

    Das ist "faktisch" korrekt. Und doch Unsinn.
    Ja, C++ ist aus C hervorgegangen und enthält C daher auch heute noch als Subset.
    Die ganze Methodik des Software-Entwurfs ist aber eine andere. Modernes C++ hat mit C quasi nichts zu tun.

    Wenn jemand ein Programm in C++ schreibt, in dem nullterminierte Strings (statt String-Klassen der Standardbibliothek), selbst gebaute verkettete Listen (statt Containerklassen), Zeigerarithmetik, oder gar Aufrufe von malloc vorkommen - der kann sein Programm zwar vielleicht kompilieren, weil all diese Sprachfeatures als C-Altlasten noch existieren, aber er hat C++ überhaupt nicht verstanden.

    Deshalb ist mir nebenbei bemerkt die ständig anzutreffende Bezeichnung "C/C++" ein totaler Graus, weil man die beiden Sprachen heute komplett getrennt voneinander sehen sollte.
    Und deshalb ist es nicht nur unnötig, sondern sogar unsinnig, erstmal C zu lernen, wenn man eigentlich in C++ entwickeln will.

    Was uns zurück zur ursprünglichen Frage führt:
    Wann ist es sinnvoll, C zu lernen, und wann ist es sinnvoll, C++ zu lernen?

    Hier kann ich thecity voll zustimmen.

    Kurz:
    C, wenn du Betriebssysteme, Treiber, Maschinensteuerungen und andere Hardware-nahe Dinge programmieren willst.
    C++ für alles andere.

    Der Grund ist: C++ abstrahiert stärker (durch den objektorientieren Ansatz), kann dadurch Polymorphismus und andere nette Dinge, die C noch völlig fremd sind, macht Typ- und Bereichsprüfungen, und bietet drüber hinaus eine umfangreiche Standardbibliothek, kurz: Es macht es sehr viel einfacher, strukturiert und fehlerfrei zu programmieren.
    Ich sage wohlgemerkt nicht, dass das in C nicht auch möglich ist, das erfordert vom Programmierer aber mehr Disziplin und Erfahrung.

    Nichtsdestotrotz ist auch C++ immer noch eine Sprache, deren Mächtigkeit und manchmal kryptische Syntax den Einsteiger leicht verwirren und bei der deshalb der Spiderman-Grundsatz gilt ("with great power comes great responsibility"). :wink:

    Ich würde deshalb C++ niemals nicht als Einsteiger-Sprache empfehlen (und C natürlich erst recht nicht).

    Ich weiß allerdings auch, dass gerade das ein kontroverses Thema ist. Frag 10 Programmierer, was sie als Einsteiger-Sprache empfehlen, und du kriegst 11 Antworten. Die höhere Abstraktion, die die "einfacheren" Programmiersprachen bieten, verhindern eben leider auch ein tieferes Verständnis dafür, was im Rechner wirklich passiert. Ganz deutlich bei der Zeiger-Problematik...
    C: Klaro, ich nehm hier einfach die Adresse vom Array, addiere zweimal die Elementgröße und bin beim dritten Element, natürlich muss ich sicher sein dass es dieses Element überhaupt gibt, sonst les ich wild in fremdem Speicher rum...
    C++: Naja, kann man mal machen wenn es nicht anders geht, aber immer schön auf nullptr prüfen...
    C#: Was ist ein Zeiger?

    Um zum Ende zu kommen: Wenn du meine Argumentation verstanden hast, sollte klar sein, ob C oder C++ das richtige für dich ist.
    Solltest du dagegen nichts oder nur wenig verstanden haben, ist mein Rat: Lass für den Anfang die Finger von allen beiden. Muss es eine von beiden sein, nimm C++. Ansonsten:
    Fang mit Python an oder C# oder wenns unbedingt sein muss Java, und beschäftige dich mit der Frage nochmal in ein paar Wochen bis Monaten, wenn du mehr Erfahrung hast.


    Beitrag zuletzt geändert: 15.11.2015 16:33:02 von annihilus
  6. Ich denke auch, dass es darauf ankommt, warum man es lernen will. Wenn es nur darum geht, programmieren zu lernen, würde ich eher C empfehlen.
    Aus eigener Erfahrung kann ich sagen, dass die Grundprinzipien, die man mit den "urtümlichen" Sprachen lernt und das logische Verständnis, was man dadurch erhält, sich sehr gut auf andere Sprachen übertragen läßt. Ok, ich habe je nach Programmiersprache immer mal wieder Probleme mit der Semantik aber bei den richtigen Sprachen verwechsle ich sie auch oft.
    Es hört sich für mich so an, als müßtest Du Dich entscheiden, ob Du den C oder den C++ Kurs besuchen sollst. Dann würde ich auch noch dazu raten, sich die Lehrer genau anzusehen. Mit dem falschen Lehrer lernst Du in der richtigen Sprache weniger als mit dem richtigen Lehrer in der falschen Sprache!
  7. Ich denke auch, dass es darauf ankommt, warum man es lernen will. Wenn es nur darum geht, programmieren zu lernen, würde ich eher C empfehlen.

    Wenn es nur darum geht, programmieren zu lernen, sollte man meiner Meinung nach weder C noch C++ lernen. Für den Alltagsgebrauch sind Sprachen wie Python einfach praktischer.
    Aus eigener Erfahrung kann ich sagen, dass die Grundprinzipien, die man mit den "urtümlichen" Sprachen lernt und das logische Verständnis, was man dadurch erhält, sich sehr gut auf andere Sprachen übertragen läßt.

    Egal, welche Sprache man lernt, man lernt immer auch irgendwelche Prinzipien, die sich auf andere Sprachen anwenden lassen. Logisches Verständnis lernt man auch sowieso bei jeder Programmiersprache. Je nachdem, was man damit anstellen will, ist es gar nicht notwendig all die „Grundprinzipien“ zu Memory Layout etc. pp. zu kennen - das wird erst bei entsprechenden Low Level Tätigkeiten und Optimierungen wichtig - auch wenn es sicherlich sinnvoll ist, sich irgendwann einmal damit zu beschäftigen, dann versteht man manchmal auch, warum manche „seltsamen“ Sprachkonstrukte sind wie sie sind.

    Ich kann dem Beitrag von annihilus nur zustimmen und mich für die Ausführung bedanken - ich wollte auch schon was über die Vermischung von C mit C++ schreiben - war aber zu faul ;)
  8. Ich habe die Erfahrung gemacht, dass einige, die heute programmieren, die tollen neuen Programme nutzen, wo man nur ein paar Klicks machen muß oder ein paar Bilder schieben, und schon erstellt die Software den Programmcode.
    Leider fehlt einigen dieser Leute vollkommen das Verständnis für die grundlegenden Zusammenhänge und damit sind sie bei Fehlern im Code auch oft überfordert. Ist so ähnlich wie Windowsanwendern, diese haben meist auch keine Ahnung mehr von Dateistrukturen oder Netzwerkstrukturen.
  9. waytogermany schrieb:
    Ich denke auch, dass es darauf ankommt, warum man es lernen will. Wenn es nur darum geht, programmieren zu lernen, würde ich eher C empfehlen.
    Aus eigener Erfahrung kann ich sagen, dass die Grundprinzipien, die man mit den "urtümlichen" Sprachen lernt und das logische Verständnis, was man dadurch erhält, sich sehr gut auf andere Sprachen übertragen läßt.

    Ja. Und gerade weil es stimmt, dass man die Grundlagen in so gut wie jeder Sprache lernen kann, gerade deshalb wähle ich als Anfänger nicht die komplizierteste auf Gottes grüner Wiese, wo ich mir drei Knoten in die Finger und zwei ins Hirn mach, nur weil ich ne simple Zeichenkette speichern und vielleicht auch noch in eine Datei schreiben will.
    Sondern da nehm ich was wie Python oder Pascal, wo ich für beides genau eine, auf Anhieb leicht verständliche Zeile brauch.
    Natürlich sind das Sprachen, in denen man bestimmt nicht sein Leben lang programmieren wird, aber hervorragend geeignet, um erst nmal die Grundlagen zu lernen, ohne vorrangig mit der Syntax kämpfen zu müssen.

    waytogermany schrieb:
    Ich habe die Erfahrung gemacht, dass einige, die heute programmieren, die tollen neuen Programme nutzen, wo man nur ein paar Klicks machen muß oder ein paar Bilder schieben, und schon erstellt die Software den Programmcode.
    Leider fehlt einigen dieser Leute vollkommen das Verständnis für die grundlegenden Zusammenhänge und damit sind sie bei Fehlern im Code auch oft überfordert.

    Diese Problematik besteht in der Tat, und ich hatte sie ja auch bereits angesprochen. Es spricht aber nichts dagegen, mit diesen einfachen Systemen erstmal anzufangen und sich dann, gewissermaßen "nach unten" vorzutasten.
    Du glaubst doch nicht, dass ein Anfänger, der von irgendwo ein 5-Zeiliges C-Programm abtippt und 10 Compiler-Fehler bekommt, nicht überfordert ist...

    waytogermany schrieb:
    Ist so ähnlich wie Windowsanwendern, diese haben meist auch keine Ahnung mehr von Dateistrukturen oder Netzwerkstrukturen.

    Und genau so muss das sein, denn Windows ist nicht für IT-Spezialisten gemacht, sondern für Otto-Normal-User. Wer sich näher mit dem technischen Unterbau beschäftigen will kann das jederzeit tun, wird dazu aber - anders als bei dem System mit dem Pinguin - nicht gezwungen.
  10. annihilus schrieb:
    Kurz:
    C, wenn du Betriebssysteme, Treiber, Maschinensteuerungen und andere Hardware-nahe Dinge programmieren willst.
    C++ für alles andere.

    Der Grund ist: C++ abstrahiert stärker (durch den objektorientieren Ansatz), kann dadurch Polymorphismus und andere nette Dinge, die C noch völlig fremd sind, macht Typ- und Bereichsprüfungen, und bietet drüber hinaus eine umfangreiche Standardbibliothek, kurz: Es macht es sehr viel einfacher, strukturiert und fehlerfrei zu programmieren.
    Ich sage wohlgemerkt nicht, dass das in C nicht auch möglich ist, das erfordert vom Programmierer aber mehr Disziplin und Erfahrung.
    In C kann man aber GLib (nicht zu verwechseln mit glibc) verwenden, das hat eigentlich alles, was man an Datenstrukturen und Utility-Funktionen braucht.

    Der Vorteil an C ist, dass man es in relativ kurzer Zeit vollständig verstehen kann. Dazu muss man "nur" K&R und "Expert C Programming" von Peter van der Linden durchgearbeitet und verstanden haben.

    Ich habe dagegen von sehr erfahrenen C++-Programmieren gehört, dass C++ es schafft, sie immer noch zu überraschen.
  11. kamakura schrieb:
    Der Vorteil an C ist, dass man es in relativ kurzer Zeit vollständig verstehen kann. Dazu muss man "nur" K&R und "Expert C Programming" von Peter van der Linden durchgearbeitet und verstanden haben.

    So eine Aussage find ich schon generell gewagt. Man lernt das Programmieren nicht durchs Lesen von zwei Büchern sondern durch lange Praxis.
    Und gerade bei C wird man "dank" fehlenden Typprüfungen, hängender Zeiger, Schreiben über Bereichsgrenzen etc. pp. auch noch nach Jahren immer mal wieder ins Klo greifen. Ein kompakter Sprachkern (woraus du wahrscheinlich die angeblich einfache vollständige Erlernbarkeit ableitest) macht eine Sprache nicht simpel, sondern eher ist das Gegenteil der Fall.

    kamakura schrieb:
    Ich habe dagegen von sehr erfahrenen C++-Programmieren gehört, dass C++ es schafft, sie immer noch zu überraschen.

    Keine Ahnung, wie das gemeint sein könnte. Bezieht sich das auf Sprachfeatures?
    Das könnte dann daran liegen, dass da die Entwicklung nicht in den 80ern aufgehört hat.
    Oder Programmverhalten?
    Da bietet C ein "Überraschungs"-Potential, da (alp-)träumst du in anderen Sprachen nur von.
  12. annihilus schrieb:
    kamakura schrieb:
    Der Vorteil an C ist, dass man es in relativ kurzer Zeit vollständig verstehen kann. Dazu muss man "nur" K&R und "Expert C Programming" von Peter van der Linden durchgearbeitet und verstanden haben.

    So eine Aussage find ich schon generell gewagt. Man lernt das Programmieren nicht durchs Lesen von zwei Büchern sondern durch lange Praxis.
    Mag sein. Aber hier geht es nicht um "das Programmieren" (wie immer man das definiert) sondern um das Verständnis der Sprache C. Hat man die beiden genannten Bücher durchgearbeitet, was das bearbeiten der Übungen darin natürlich mit einschließt, dann wird man C vollständig verstanden haben, heißt: Es gibt keine Syntaxkonstruktionen oder Eigenheiten der Laufzeitumgebung mehr, die man nicht versteht.
    Und gerade bei C wird man "dank" fehlenden Typprüfungen, hängender Zeiger, Schreiben über Bereichsgrenzen etc. pp. auch noch nach Jahren immer mal wieder ins Klo greifen.
    Kannst du zu den fehlenden Typprüfungen Beispiele bringen? C hat Typprüfungen. Ok, etwas wie int *x = 8; ist nicht valide in C++ und erlaubt in C. Aber macht das in der Praxis so einen Unterschied? Ich hab das mit drei C-Compilern getestet und jeder gab da in der Standardeinstellung eine Warnung aus. Ach, ja, variadische Funktionen (wie printf) haben auch keine Typprüfung :rolleyes: aber so oft kommen die nun auch nicht vor.

    Und sind C++-Referenzen denn sicherer als C-Pointer? Was bei dieser ganzen Pointer-Referenzen-Diskussion untergeht, ist, dass allein nur die Existenz eines Garbage-Collectors einen wesentlichen Unterschied machen kann. Bei Go und Java ist aufgrund des Garbage-Collectors garantiert, dass Pointer (Go) bzw. Referenzen (Java) nicht ins Leere zeigen. C und C++ haben aber keinen Garbage-Collector, allein schon daher können ihre Pointer/Referenzen gar nicht sicher sein. Die Existenz von C++-Referenzen neben klassischen Pointern hat eigentlich nur eine Rechtfertigung, nämlich dass Referenzen das Operator-Overloading von [] für Zuweisungen ermöglichen.

    Auch C++ liefert natürlich keine Arraygrenzen-Überwachung auf fundamentaler Ebene wie Go oder Java. Wenn man wenigstens den schwachen Abklatsch davon haben will, muss man die Container-Klassen aus der STL verwenden. Aber hierin allein kann der Vorteil nicht liegen, denn was ist da der große Unterschied zu C mit Verwendung von C-Bibliotheken mit quasi-Container-"Klassen"?
    Ein kompakter Sprachkern (woraus du wahrscheinlich die angeblich einfache vollständige Erlernbarkeit ableitest) macht eine Sprache nicht simpel, sondern eher ist das Gegenteil der Fall.
    Ich habe nie gesagt, dass C eine einfach zu erlernende Sprache ist (nur im Vergleich zu C++).

    Es ist sinnlos, hier all die zahllosen C-Kuriosa aufzulisten (hinter manchen entdeckt man mit mehr Erfahrung einen tiefereren Sinn. Manche sind einfach nur sinnlos skurril), die Klassiker wie
    if(x = 1) {
    // Code hier wird sicher ausgeführt und x wurde auf 1 gesetzt
    }
    kennt ja jeder (mit den richtigen Warneinstellungen des Compilers ist man vieles schon los). Auch der Arraytyp von C ist sehr erheiternd: Er existiert zwar als eigener Typ (und ist kein Pointer!), aber kaum schaut man hin, ist er schon in einen Pointer kollabiert. Wie im Märchen.

    Go wäre für mich eine einfache Sprache: Die Syntax ist nicht umfangreicher als C aber ohne Kuriosa und das Sich-Dummstellen von C und mit richtigem import statt #include. Und es gibt einen Garbage-Collector!

    Eine interessante Frage ist nun: Kann man in C++ programmieren, ohne sich mit dem C-Kuriositätenkabinett auseinandersetzen zu müssen? Du hast geschrieben:
    Modernes C++ hat mit C quasi nichts zu tun.
    Mag sein, dass man in 95% der Fälle C-typische Konstrukte vermeiden kann. Aber was ist mit den restlichen 5%? Um ein halbwegs kompetenter Programmierer zu sein, sollte man keine solchen blind spots haben. Um die ganzen C-Kuriosa wie mit Pointern (this ist ein Pointer), sequence-points (Geht folgendes: int x = 3, &y = x; ?), dem Präprozessor (Include-Guards braucht man auch in C++), nullterminierten Strings (kommt schon bei int main(int argc, char *argv[]) vor) oder C-Arrays (anders bekommt man echte, d.h. halbwegs performante, mehrdimensionale Arrays nicht hin) kommste nicht drum rum.

    Ok, ist das, was "High Level" an C++ ist, wenigstens einfacher zu benutzen als C mit guten Bibliotheken?

    Sowohl C als auch C++ haben (nachdem der Präprozessor durchgelaufen ist) keine kontextfreie Grammatik. Aber C wird nur durch typedef kontextabhängig. Z.B. je nachdem, welche der beiden Zeilen du auskommentierst, ist die dritte Zeile eine Deklaration oder eine Multiplikation:
    // typedef int a;
    // int a = 1, b = 2;
    a * b;
    C++ ist dagegen extrem kontextabhängig. Je nachdem, welche der beiden Zeilen du in folgendem C++-Code auskommentierst
    // int aa, bb, cc(int);
    // struct aa {int x, y;} *bb;
    aa * cc(bb);
    ist die dritte Zeile ein Ausdruck oder eine Deklaration. In validem C muss die dritte Zeile jedoch sicher ein Ausdruck sein.
    Die Metaprogrammierbarkeit in C++ ist so umfangreich, dass sie selber schon eine vollständige Programmiersprache bildet. Man kann den Compiler in eine Endlosschleife schicken oder Primzahlen über Templates während des Kompilierens berechnen. Mir ist keine Programmiersprache außer C++ bekannt, die eine solche Komplexität (Kontextabhängigkeit + Metaprogrammierung) erreicht.

    So, dann egal wie brav man böse Operationen vermeidet: C++ erlaubt direkten Zugriff auf den Speicher und damit wird wohl jeder mit Korruptionen von Objekten auf dem Free Store konfrontiert werden. Bei einem Code wie
    #include <vector>
    #include <iostream>
    
    
    int main(int argc, char *argv[]){
      std::vector<int> vec;
      for (int j=0; j<1000; j++) {
          vec.push_back(j);
      }
      int * boese = (int *) &vec;
      boese[2] = -1;
      int i = 1010;
      vec.at(i) = 777;
      std::cout << "vec.at(" << i << ") = " << vec.at(i) << std::endl;
      return 0;
    }
    funktioniert die Überwachung der Bereichsgrenzen von std::vector nicht mehr.

    Die Frage ist nun: Kann man C++ genauso gut debuggen wie C? Weder der AddressSanitizer, noch Electric Fence, noch Valgrind finden den Bug. Bei äquivalenten Spielchen mit C und malloc schlagen sie sofort an.
    Aber ich kenne mich was C++-Debuggen angeht leider nicht gut aus. Hast du irgendwelche Ideen?

    Falls man Bugs mit Objekt-Korruption schlechter beheben kann als Pufferüberläufe in C (und so sieht es aus), dann sehe ich keinen Vorteil von C++ was die Fehleranfälligkeit angeht. C++ warnt einen zwar komfortabel vor gewöhnlichen Fehlern, wenn sonst alles ok läuft, falls jedoch nicht, dann scheint es im Vergleich zu C richtig heftig zu werden.
    kamakura schrieb:
    Ich habe dagegen von sehr erfahrenen C++-Programmieren gehört, dass C++ es schafft, sie immer noch zu überraschen.

    Keine Ahnung, wie das gemeint sein könnte. Bezieht sich das auf Sprachfeatures?
    Ich denke ja. Die Komplexität von C++ ist wirklich atemberaubend. Aber das ist anekdotische Evidenz, also lassen wir das.
    Das könnte dann daran liegen, dass da die Entwicklung nicht in den 80ern aufgehört hat.
    Verglichen mit C++ ist C natürlich relativ stabil. C11 ist aber schon eine moderne Programmiersprache mit Unicode-Support, Multithreading, echten Boolschen Variablen, generischen Funktionen, freier Möglichkeit seine Variablen zu definieren, lokalen Schleifenvariablen, usw. :-) Sollte natürlich selbstverständlich sein aber ist auch tatsächlich drin!
    Oder Programmverhalten?
    Da bietet C ein "Überraschungs"-Potential, da (alp-)träumst du in anderen Sprachen nur von.
    Im Vergleich zu allen Sprachen mit Garbage-Collector ist C äußerst "überraschend". Aber ist es schlimmer als C++?

    Wenn C wirklich so problematisch wäre, d.h. sich leicht Fehler einschleichen (relativ unkontroverse Behauptung), die gleichzeitig (!) schwer zu debuggen sind (?? das ist eben die große Frage...), dann müsste sich das empirisch irgendwie auch feststellen lassen. Warum lässt sich überhaupt stabile, sehr umfangreiche Anwendungssoftware wie z.B. GIMP, CPython, Stata, SAS, Maple (der Kern), der Apache Web Server oder Git mit reinem C bewerkstelligen?

    Empirisch stellt man natürlich auch fest, dass es extrem viel C++-Software gibt, die sehr umfangreich und stabil ist. Aber bei Adobe o.ä. arbeiten (hoffentlich!) auch keine Hobby-Programmierer wie wir hier (oder zumindest der Threadersteller), sondern Profis, von denen man verlangen kann, dass sie auch eine extrem komplexe Sprache gut zu beherrschen lernen.

    Beitrag zuletzt geändert: 19.4.2016 4:03:38 von kamakura
  13. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    annihilus schrieb:
    Ein kompakter Sprachkern (woraus du wahrscheinlich die angeblich einfache vollständige Erlernbarkeit ableitest) macht eine Sprache nicht simpel, sondern eher ist das Gegenteil der Fall.
    Bestes Beispiel dafür: Assembler. Die Syntax lässt sich selbst mit einem DFA parsen, aber um auch nur irgendetwas damit tun zu können, muss man die (abstrakte) Arbeitsweise der CPU, des OS usw verstanden haben. Das Problem ist hier also: die Sprache hat man sehr schnell verstanden, aber auch nicht mehr. Nur braucht man dieses »mehr« (z.B. I/O), um mit der Sprache sinnvoll etwas anfangen zu können.

    kamakura schrieb:
    Hat man die beiden genannten Bücher durchgearbeitet, was das bearbeiten der Übungen darin natürlich mit einschließt, dann wird man C vollständig verstanden haben, heißt: Es gibt keine Syntaxkonstruktionen oder Eigenheiten der Laufzeitumgebung mehr, die man nicht versteht.
    Syntaxkonstruktion wohl nicht, allerdings gibt es durchaus Compiler- oder Bibliotheks-Eigenheiten, die du nicht verstehst. Dafür musst du die auch nicht verstehen, da es sich dabei um nicht spezifiziertes Verhalten handelt :-P
    Viel wichtiger ist dabei sowieso zu wissen, was überhaupt in diese Kategorie fällt und wie man das vermeidet.

    kamakura schrieb:
    Kannst du zu den fehlenden Typprüfungen Beispiele bringen?
    Vermutlich meint er Laufzeit-Typinformation, die es in C überhaupt nicht gibt.

    Und sind C++-Referenzen denn sicherer als C-Pointer? Was bei dieser ganzen Pointer-Referenzen-Diskussion untergeht, ist, dass allein nur die Existenz eines Garbage-Collectors einen wesentlichen Unterschied machen kann. Bei Go und Java ist aufgrund des Garbage-Collectors garantiert, dass Pointer (Go) bzw. Referenzen (Java) nicht ins Leere zeigen. C und C++ haben aber keinen Garbage-Collector, allein schon daher können ihre Pointer/Referenzen gar nicht sicher sein.
    Richtig, allerdings ist die Aussage, dass C++ keinen GC hat mittlerweile auch überholt, da
    smart_ptr
    u.ä. einen rudimentären GC im Hintergrund nutzen, auch wenn du das natürlich nicht verwenden musst. Das nur der Vollständigkeit halber.

    Bei Go und Java ist aufgrund des Garbage-Collectors garantiert, dass Pointer (Go) bzw. Referenzen (Java) nicht ins Leere zeigen.
    Es gibt allerdings in Java durchaus auch Möglichkeiten, eigenartige Referenzen zu konstruieren oder unsicheren Speicher anzufordern. Man muss das allerdings ganz bewusst und absichtlich tun.

    Sowohl C als auch C++ haben (nachdem der Präprozessor durchgelaufen ist) keine kontextfreie Grammatik. Aber C wird nur durch typedef kontextabhängig.
    Kannst du diese Behauptung auch irgendwie belegen? Die Syntax basiert jedenfalls auf einer kontextfreien Grammatik (gilt auch für C++, darfst du gern selbst suchen), und durch Typinformation (die du nach dem Parsen erst im Semantikanschluss verarbeitest) ist die Sprache der gültigen (= auch semantisch korrekten) C-Programme (so wie übrigens bei den meisten Programmiersprachen) kontextsensitiv. Aber was will das mit
    typedef
    zu tun haben?

    kamakura schrieb:
    C++ ist dagegen extrem kontextabhängig. Je nachdem, welche der beiden Zeilen du in folgendem C++-Code auskommentierst
    // int aa, bb, cc(int);
    // struct aa {int x, y;} *bb;
    aa * cc(bb);
    ist die dritte Zeile ein Ausdruck oder eine Deklaration. In validem C muss die dritte Zeile jedoch sicher ein Ausdruck sein.
    … was allerdings daran liegt, dass in C ein
    struct
    -Datentyp nicht den selben Namensraum nutzt wie alles andere. Änderst du dein Codebeispiel und fügst eine weitere Zeile ein, sodass
    aa
    im selben Namensraum verfügbar wird, in dem du es auch suchst, sagt der Compiler darüber, dass der Parameter nur einen Namen hat, aber keinen Typ (alleine um das feststellen zu können braucht er schon einen Kontext), allerdings übersetzt er (mit c89, pedantic):
    void f(void)
    {
    #ifdef A
            int aa, bb, cc(int);
    #else
            struct aa { int x, y; } *bb; typedef struct aa aa;
    #endif
            aa * cc(bb);
    }
    Ausgabe:
    % gcc -std=c89 -pedantic test.c -c -o test.o
    test.c: In function ‘f’:
    test.c:8:2: warning: parameter names (without types) in function declaration
      aa * cc(bb);
      ^
    Das zusätzliche
    typedef
    (ein
    Decl
    in der zuvor verlinkten Grammatik) ändert ja syntaktisch nichts an der letzten Zeile, allerdings an der Semantik. Das Gute daran: die Variante ohne definiertem
    A
    hat in C eine völlig andere Bedeutung als in C++. Falls das zeigen soll: durch
    typedef
    kann man die Semantik von Statements ändern: korrekt. Falls das zeigen soll, dass erst durch
    typedef
    die Sprache C kontextsensitiv wird: falsch, das ist sie auch so. Beispiel:
    void f(void) {
            a->x = y % 2;
    }
    Ist dieses Programmfragment gültig? Wenn es sich um eine kontextfreie Sprache handeln würde, müsstest du das jetzt entscheiden können. Da dies aber davon abhängt, welchen Typ
    a
    und
    y
    hat, hast du hier einen Kontext. In der Realität ist das aber sowieso relativ egal, da praktisch jeder Parser die kontextfreie Syntax parst, und hinterher erst auswertet, ob das semantisch korrekt ist. Du hast allerdings recht, wenn du sagst, dass die C++-Syntax extrem komplex ist, nicht umsonst parst man C++ normalerweise Bottom-Up und nicht Top-Down.

    Abschließend sei noch gesagt: gut, dass sich VM-Technologie recht brauchbar entwickelt, und mittlerweile schon selbst C auf der JVM mit recht geringem Performance-Verlust im Vergleich zu einem nativen Binary läuft. Denn somit muss man nicht mehr alles in C schreiben um schnell zu sein, oder alles in Java o.ä. um einfach zu sein (grob gesagt), sondern kann fast alles in Java o.ä. bauen und für bestimmte Programmteile auf Features von C zurückgreifen. Ganz ohne durch diese Sprachmischung einen Overhead, der sich negativ auf die Performance auswirkt, zu bekommen.

    @Topic
    Ob man nun mit C oder C++ anfangen sollte, wenn man bereits programmieren kann: C ist sicher die bessere Wahl. Kurz zusammengefasst warum: weil C eben doch die Basis von C++ darstellt (nicht nur zufällig sind viele C-Programme auch gültige C++-Programme). Der Rest wurde hier hoffentlich schon ausführlich genug erklärt.

    Beitrag zuletzt geändert: 19.4.2016 20:25:16 von hackyourlife
  14. kamakura schrieb:
    Aber hier geht es nicht um "das Programmieren" (wie immer man das definiert) sondern um das Verständnis der Sprache C. Hat man die beiden genannten Bücher durchgearbeitet, was das bearbeiten der Übungen darin natürlich mit einschließt, dann wird man C vollständig verstanden haben, heißt: Es gibt keine Syntaxkonstruktionen oder Eigenheiten der Laufzeitumgebung mehr, die man nicht versteht.

    Naja, es ging eigentlich doch ums Programmieren, denn man lernt eine Programmiersprache ja nicht um sie zu kennen, sondern um sie anzuwenden. Und da es ums Einsteigen geht, sind Sprachen, die den Programmierer nicht ein wenig an die Hand nehmen, da meiner Meinung nach nicht gut geeignet.

    kamakura schrieb:
    Kannst du zu den fehlenden Typprüfungen Beispiele bringen? C hat Typprüfungen. Ok, etwas wie int *x = 8; ist nicht valide in C++ und erlaubt in C. Aber macht das in der Praxis so einen Unterschied?

    Die Frage der Praxisrelevanz kann man natürlich immer stellen, letztlich muss man aber berücksichtigen, dass gewisse Effekte einen Neuling überraschen werden, die für einen "alten Hasen" klar sind.
    Komplett willkürliches Beispiel:
    if (4 <= 3 <= 2) {
    // wird ausgeführt
    }

    Das geht dehalb, weil es entweder gar keinen booleschen Datentyp gibt oder aber aus Gründen der Abwärtskompatibilität implizit nach int gecastet wird.
    Für einen Anfänger sind Sprachen besser, in denen man so etwas erst gar nicht schreiben darf.

    kamakura schrieb:
    Und sind C++-Referenzen denn sicherer als C-Pointer?

    Ja, sind sie, denn immerhin können sie zumindest bei der Übergabe nicht Null oder ungültig sein. Referenzen sind aber nur ein Aspekt, ein anderer wären z.B. Smart Pointer oder zumindest, dass man Zeiger außerhalb von Klassen vermeidet.

    kamakura schrieb:
    Was bei dieser ganzen Pointer-Referenzen-Diskussion untergeht, ist, dass allein nur die Existenz eines Garbage-Collectors einen wesentlichen Unterschied machen kann. Bei Go und Java ist aufgrund des Garbage-Collectors garantiert, dass Pointer (Go) bzw. Referenzen (Java) nicht ins Leere zeigen. C und C++ haben aber keinen Garbage-Collector, allein schon daher können ihre Pointer/Referenzen gar nicht sicher sein.

    Das ist schlicht falsch, man kann Pointer sehr einfach durch RAII absichern, oder, wie gesagt, Smart Pointer verwenden.

    kamakura schrieb:
    Auch C++ liefert natürlich keine Arraygrenzen-Überwachung auf fundamentaler Ebene wie Go oder Java.

    Natürlich nicht. Kann ja nicht, wegen der vermaledeiten C-Kompatibilität.
    Deshalb kann man selbstverständlich jeden Unfug, den man in C treiben kann, auch in C++ machen, muss man aber nicht. (Übrigens ein weiterer Punkt, warum C++ für Anfänger schlecht geeignet ist; das ist wie ein Werkzeugkasten, aus dem man nur die Hälfte der Tools benutzen darf oder sollte, aber man weiß anfangs nicht so genau welche Hälfte).

    kamakura schrieb:
    Wenn man wenigstens den schwachen Abklatsch davon haben will, muss man die Container-Klassen aus der STL verwenden. Aber hierin allein kann der Vorteil nicht liegen, denn was ist da der große Unterschied zu C mit Verwendung von C-Bibliotheken mit quasi-Container-"Klassen"?

    Die Kapselung.

    kamakura schrieb:
    Es ist sinnlos, hier all die zahllosen C-Kuriosa aufzulisten (hinter manchen entdeckt man mit mehr Erfahrung einen tiefereren Sinn. Manche sind einfach nur sinnlos skurril), die Klassiker wie
    if(x = 1) {
    // Code hier wird sicher ausgeführt und x wurde auf 1 gesetzt
    }
    kennt ja jeder (mit den richtigen Warneinstellungen des Compilers ist man vieles schon los). Auch der Arraytyp von C ist sehr erheiternd: Er existiert zwar als eigener Typ (und ist kein Pointer!), aber kaum schaut man hin, ist er schon in einen Pointer kollabiert. Wie im Märchen.

    Genau. Und als erfahrener Programmierer kennt man diese Fallstricke und umgeht sie. Das ändert nichts daran, dass das eigentlich schlechtes Design ist. Und übrigens ist auch dieser Kappes wieder auf fehlende Typprüfung zurückzuführen! Denn ein Problem kann aus "if (x=1)" nur in einer Sprache entstehen, in der ein boolesches "True" und ein Integer "1" entweder dasselbe sind oder implizit ineinander konvertiert werden. In einer Wirth-Sprache etwa kannst du so etwas schlicht nicht machen.

    kamakura schrieb:
    Eine interessante Frage ist nun: Kann man in C++ programmieren, ohne sich mit dem C-Kuriositätenkabinett auseinandersetzen zu müssen? Du hast geschrieben:
    Modernes C++ hat mit C quasi nichts zu tun.
    Mag sein, dass man in 95% der Fälle C-typische Konstrukte vermeiden kann. Aber was ist mit den restlichen 5%? Um ein halbwegs kompetenter Programmierer zu sein, sollte man keine solchen blind spots haben.

    Das sehe ich gerade umgekehrt; um gutes, modernes C++ zu schreiben, muss man alte C-Vorgehensweisen unbedingt strikt vermeiden. Und genau weil man das als Anfänger nicht kann - weil man noch nicht weiß, was was ist, und weil man Codebeispiele im Internet findet, die alles immer munter miteinander verquicken etc., genau deshalb ist C++ für Anfänger schlecht geeignet.

    kamakura schrieb:
    Um die ganzen C-Kuriosa wie mit Pointern (this ist ein Pointer), sequence-points (Geht folgendes: int x = 3, &y = x; ?), dem Präprozessor (Include-Guards braucht man auch in C++), nullterminierten Strings (kommt schon bei int main(int argc, char *argv[]) vor) oder C-Arrays (anders bekommt man echte, d.h. halbwegs performante, mehrdimensionale Arrays nicht hin) kommste nicht drum rum.

    Kommt drauf an, wie man "drum rum kommen" definiert. An einer einzigen Stelle einen nullterminierten String benutzen zu müssen oder permanent damit zu hantieren sind dann doch zwei verschiedene paar Schuhe.
    Wäre es besser, wenn es diese Altlasten nicht gäbe? Klar. Ist ja einer der Gründe, warum C++ nix für Anfänger ist. Aber C ist es halt erst recht nicht.

    kamakura schrieb:
    Sowohl C als auch C++ haben (nachdem der Präprozessor durchgelaufen ist) keine kontextfreie Grammatik. Aber C wird nur durch typedef kontextabhängig. Z.B. je nachdem, welche der beiden Zeilen du auskommentierst, ist die dritte Zeile eine Deklaration oder eine Multiplikation:
    // typedef int a;
    // int a = 1, b = 2;
    a * b;
    C++ ist dagegen extrem kontextabhängig. Je nachdem, welche der beiden Zeilen du in folgendem C++-Code auskommentierst
    // int aa, bb, cc(int);
    // struct aa {int x, y;} *bb;
    aa * cc(bb);
    ist die dritte Zeile ein Ausdruck oder eine Deklaration. In validem C muss die dritte Zeile jedoch sicher ein Ausdruck sein.

    Wow. Das Beispiel scheint mir extrem akademisch. Aber vielleicht ist es auch nur Zufall, dass ich in all den Jahren noch niemals so ein Problem hatte... sei's drum, der Punkt ist: Ich hab nie behauptet, C++ sei ne perfekte Sprache.

    kamakura schrieb:
    Die Metaprogrammierbarkeit in C++ ist so umfangreich, dass sie selber schon eine vollständige Programmiersprache bildet. Man kann den Compiler in eine Endlosschleife schicken oder Primzahlen über Templates während des Kompilierens berechnen. Mir ist keine Programmiersprache außer C++ bekannt, die eine solche Komplexität (Kontextabhängigkeit + Metaprogrammierung) erreicht.

    Ja, darüber müssen wir nicht streiten. Makros in C++ sind so mächtig dass es schon lächerlich ist. Aber man muss sie ja nicht benutzen.

    kamakura schrieb:
    So, dann egal wie brav man böse Operationen vermeidet: C++ erlaubt direkten Zugriff auf den Speicher und damit wird wohl jeder mit Korruptionen von Objekten auf dem Free Store konfrontiert werden. Bei einem Code wie
    #include <vector>
    #include <iostream>
    
    int main(int argc, char *argv[]){
      std::vector<int> vec;
      for (int j=0; j<1000; j++) {
          vec.push_back(j);
      }
      int * boese = (int *) &vec;
      boese[2] = -1;
      int i = 1010;
      vec.at(i) = 777;
      std::cout << "vec.at(" << i << ") = " << vec.at(i) << std::endl;
      return 0;
    }
    funktioniert die Überwachung der Bereichsgrenzen von std::vector nicht mehr.

    Sehr schönes Beispiel. Nämlich dafür, wie ein Anfänger sehr leicht in die Falle tappen könnte, Konzepte aus C und C++ nicht auseinanderhalten zu können (oder zu wollen). So etwas wie du da gebastelt hast meinen die Leute wahrscheinlich, wenn sie von "C/C++" sprechen. Da fehlt eigentlich nur noch ein schönes malloc() oder Ähnliches. :)
    Ein Paradebeispiel dafür, wie man Zeiger in C++ auf gar keinen Fall benutzt. Nämlich erstens "nackt" außerhalb einer Klasse, zweitens schön in eine Fremdklasse reinpointernd.
    Das verletzt jeden Grundsatz von information hiding, Datenkapselung, und RAII. Das sind nun aber Grundsätze, die man als Programmierer selbst umsetzen muss. Weil einen der Compiler nicht daran hindert, C++ wie C zu benutzen, genau deshalb ist es für Anfänger nix.

    kamakura schrieb:
    Die Frage ist nun: Kann man C++ genauso gut debuggen wie C? Weder der AddressSanitizer, noch Electric Fence, noch Valgrind finden den Bug. Bei äquivalenten Spielchen mit C und malloc schlagen sie sofort an.
    Aber ich kenne mich was C++-Debuggen angeht leider nicht gut aus. Hast du irgendwelche Ideen?

    Nein. Wer sowas ernsthaft programmiert, dem kann kein Debugger mehr helfen. Wenn ich in einer OO-Sprache programmieren will sollte ich schon das Konzept einer Klasse verstanden haben. Ich stürz mich als Nichtschwimmer auch nicht in den Atlantik und jammere dann dass Baywatch gerade pennt.

    kamakura schrieb:
    Falls man Bugs mit Objekt-Korruption schlechter beheben kann als Pufferüberläufe in C (und so sieht es aus), dann sehe ich keinen Vorteil von C++ was die Fehleranfälligkeit angeht. C++ warnt einen zwar komfortabel vor gewöhnlichen Fehlern, wenn sonst alles ok läuft, falls jedoch nicht, dann scheint es im Vergleich zu C richtig heftig zu werden.

    Du hattest in diesem konkreten Beispiel aber Wissen über den internen Aufbau der verwendeten Klasse (Sinn der OOP ist, dieses gerade nicht zu haben), und hast es bewusst dazu verwendet, das Schutzkonzept, welches Klassen normalerweise bieten, gezielt auszuhebeln. Aber stimmt: Man kriegt es kaputt, wenn man es drauf anlegt. Wie alles.

    Da könnte man einwenden: Wenn es aber "kaputtbar" ist, ist es nicht idiotensicher, und man kann es dann auch aus Versehen oder Unwissenheit kaputtmachen. Absolut falsch.
    Du hast einen std::Vector<int> genommen und ihn bewusst und explizit nach int* gecastet. So was passiert nicht aus Unachtsamkeit, dafür muss man bösartig sein. Wie deine Wahl des Variablennamens ja auch zeigt. :)

    kamakura schrieb:
    Im Vergleich zu allen Sprachen mit Garbage-Collector ist C äußerst "überraschend". Aber ist es schlimmer als C++?

    Ich bleibe dabei, dass C++ sicherer ist, räume nach dieser Diskussion aber gerne ein: Nur wenn man weiß was man tut und konsequent die Prinzipien der OOP anwendet. Nicht so einfach von selbst und out of the box.

    kamakura schrieb:
    Wenn C wirklich so problematisch wäre, d.h. sich leicht Fehler einschleichen (relativ unkontroverse Behauptung), die gleichzeitig (!) schwer zu debuggen sind (?? das ist eben die große Frage...), dann müsste sich das empirisch irgendwie auch feststellen lassen. Warum lässt sich überhaupt stabile, sehr umfangreiche Anwendungssoftware wie z.B. GIMP, CPython, Stata, SAS, Maple (der Kern), der Apache Web Server oder Git mit reinem C bewerkstelligen?

    Empirisch stellt man natürlich auch fest, dass es extrem viel C++-Software gibt, die sehr umfangreich und stabil ist. Aber bei Adobe o.ä. arbeiten (hoffentlich!) auch keine Hobby-Programmierer wie wir hier (oder zumindest der Threadersteller), sondern Profis, von denen man verlangen kann, dass sie auch eine extrem komplexe Sprache gut zu beherrschen lernen.

    Aber für GIMP, CPython, Stata, SAS, Maple, Apache Webserver oder Git arbeiten n00bs, die mit C zurechtkommen weil es simpel ist und nicht etwa weil es erfahrene Entwickler sind... irgendwie argumentierst du da ziemlich willkürlich.

    Es ist unbestritten, dass man mit C oder C++ gute Software entwickeln kann. Nur würd ich als Anfänger (erstmal) die Finger davon lassen. Das ist alles.
  15. @hackyourlife: was hat die verlinkte Datei für eine Grammatik? Definitiv nicht yacc. Und dass nur das typedef ein Problem macht, steht sogar in den Comments (ganz oben) der verlinkten Datei.
    Dass Variablen vor Benutzung deklariert werden oder den richtigen Typ haben müssen, wird üblicherweise nicht zu Syntax gerechnet. Sonst wäre praktisch keine Programmiersprache kontextfrei.

    annihilus schrieb:
    Naja, es ging eigentlich doch ums Programmieren, denn man lernt eine Programmiersprache ja nicht um sie zu kennen, sondern um sie anzuwenden.
    Sorry, ich finde den Satz

    "Man lernt das Programmieren nicht durchs Lesen von zwei Büchern sondern durch lange Praxis."

    ähnlich aussagelos wie

    "Man lernt die Mathematik nicht durchs Lesen von zwei Büchern sondern durch lange Praxis."

    Was ist denn "das Programmieren"?
    Das geht dehalb, weil es entweder gar keinen booleschen Datentyp gibt oder aber aus Gründen der Abwärtskompatibilität implizit nach int gecastet wird.
    Ja, aber in C++ besteht dieses Problem ja weiterhin. C++ hat viele implizite Typenumwandlungen.
    Ja, sind sie, denn immerhin können sie zumindest bei der Übergabe nicht Null oder ungültig sein.
    Hängende Referenzen:
    #include <iostream>
    
    using namespace std;
    
    int main() {
        int *x = new int(-12345);
        delete x;
    
        int *z = new int(-6789);
    
        int& y = (int&) *x;
        cout << "y = " << y << endl;
    
        return 0;
    }
    Ausgabe:
    y = -6789
    (!!!)
    Das ist schlicht falsch, man kann Pointer sehr einfach durch RAII absichern, oder, wie gesagt, Smart Pointer verwenden.
    Unsichere smart pointer:
    #include <iostream>
    #include <memory>
    
    using namespace std;
    
    unique_ptr<int> f(int k){
      auto x = make_unique<int>(k);
      return x;
    }
    
    int &a = *f(-12345); // genial ;-)
    
    int main () {
      f(-6789);
      cout << "a = " <<  a << endl;
      return 0;
    }
    Ausgabe:
    a = -6789
    (!!!)
    Die Kapselung.
    Geht mit opaque pointers (so wird es z.B. in GLib gemacht).

    Genau. Und als erfahrener Programmierer kennt man diese Fallstricke und umgeht sie. Das ändert nichts daran, dass das eigentlich schlechtes Design ist.
    C war halt als minimalistische, Hardware-nahe, Compiler-freundliche, schnelle Sprache gedacht. Nicht als einfach verständliche.

    C++ erbt die C-Kuriosa und ist zudem noch abartig umfangreich, komplex und schwer zu parsen (schlecht für Debugger und IDEs).
    genau deshalb ist C++ für Anfänger schlecht geeignet.
    Da sind wir ja einer Meinung. ;-)
    An einer einzigen Stelle einen nullterminierten String benutzen zu müssen oder permanent damit zu hantieren sind dann doch zwei verschiedene paar Schuhe.
    Was ist mit den anderen Beispielen? Eigen (die Bibliothek) verwendet intern z.B. klassische C-Arrays.
    Die C-Kompatibilität ist ein zentrales Feature des Designs von C++. Wenn man sie eigentlich gar nicht benutzen darf, hätte man ja auch darauf verzichten können.
    Klar. Ist ja einer der Gründe, warum C++ nix für Anfänger ist. Aber C ist es halt erst recht nicht.
    Nur wenn man in C++ programmieren könnte ohne mit den C-Altlasten konfrontiert zu werden.
    Wow. Das Beispiel scheint mir extrem akademisch.
    Sämtliche Beispiele, die ich hier bringe, sind akademisch. Es sind immer proof-of-concept-Beispiele. Realistische Beispiele wären viel länger und schwer verständlich.
    Ja, darüber müssen wir nicht streiten. Makros in C++ sind so mächtig dass es schon lächerlich ist. Aber man muss sie ja nicht benutzen.
    Dann hoffen wir mal, dass sie auch andere Programmierer nicht benutzen, ansonsten versteht man deren Code nicht.

    Und die mächtige Metaprogrammierung ist für Tools wie IDEs, static analysis und Debugger auch ein Problem.
    Nein. Wer sowas ernsthaft programmiert, dem kann kein Debugger mehr helfen. Wenn ich in einer OO-Sprache programmieren will sollte ich schon das Konzept einer Klasse verstanden haben. Ich stürz mich als Nichtschwimmer auch nicht in den Atlantik und jammere dann dass Baywatch gerade pennt.
    Das Beispiel war an den Haaren herbeigezogen. Ansonsten wäre es nicht so kurz und leicht verständlich geworden. Objekt-Korruption und Heap-Korruption ist aber ein reales Problem. Realistische Beispiele findest du auf Stackoverflow:

    http://stackoverflow.com/search?q=heap+corruption+[c%2B%2B] (sorry, der Lima-URL-Tag kommt mit Brackets im Link nicht klar)

    Solche Bugs können jedem passieren, die sollte man also hoffentlich auch irgendwie debuggen können.
    Aber für GIMP, CPython, Stata, SAS, Maple, Apache Webserver oder Git arbeiten n00bs, die mit C zurechtkommen weil es simpel ist und nicht etwa weil es erfahrene Entwickler sind... irgendwie argumentierst du da ziemlich willkürlich.
    Nein, so war das nicht gemeint. Die Frage ist, wie das mit folgender deiner Aussagen zusammenpasst:
    Kurz:
    C, wenn du Betriebssysteme, Treiber, Maschinensteuerungen und andere Hardware-nahe Dinge programmieren willst.
    C++ für alles andere.


    Beitrag zuletzt geändert: 27.4.2016 17:25:56 von kamakura
  16. onlinevideorecorder

    onlinevideorecorder hat kostenlosen Webspace.

    Ich wollte mal erwähnen, dass noch eine dritte Programmiersprache dieser Art veröffentlicht wurde (rust).

    https://www.rust-lang.org/
  17. kamakura schrieb:
    Ja, aber in C++ besteht dieses Problem ja weiterhin. C++ hat viele implizite Typenumwandlungen.

    Dir ist wohl noch nicht klar geworden, dass mein primäres Anliegen hier nicht ist, C++ zu rühmen, sondern Anfängern nahezulegen, die Finger davon zu lassen. Was du da schreibst habe ich ja fast 1:1 auch geschrieben.

    kamakura schrieb:
    Hängende Referenzen: ...
    Unsichere smart pointer: ...

    Das ist aus dem gleichen Gruselkabinett wie dein voriges Vector-Beispiel: Den Karren mit 300 Klamotten sehenden Auges vor die Wand setzen und dann den Hersteller des Sicherheitsgurtes verklagen.
    Wenn ich von den sicher(er)en Mechanismen in C++ profitieren will, darf ich sie logischerweise nicht blöd auf C-Style-Zeiger casten, weil ich dann wenig gewonnen hab.
    Nebenbei trotzdem besser als nichts: In deiner Referenz steht zwar Blödsinn (weil du explizit Blödsinn reingeschrieben hast), aber du kriegst keine Schutzverletzung, wie du sie mit einem Zeiger unweigerlich provoziert haben würdest.

    kamakura schrieb:
    C war halt als minimalistische, Hardware-nahe, Compiler-freundliche, schnelle Sprache gedacht. Nicht als einfach verständliche.

    Ach was? War der Ausgangspunkt der ganzen Diskussion nicht genau der, dass du das Gegenteil behauptet hast? Von wegen zwei Bücher und so?

    kamakura schrieb:
    Was ist mit den anderen Beispielen? Eigen (die Bibliothek) verwendet intern z.B. klassische C-Arrays.

    Da habe ich mir geschenkt, tiefer drauf einzugehen, weils die gleiche Güteklasse ist: So etwas kann ich benutzen wenn ich gezwungen bin (meistens durch externe Gründe wie eine Bibliothek die ich benutzen muss), würde ich in C++ aber niemals einsetzen wenn ich eine Wahl habe.

    kamakura schrieb:
    Die C-Kompatibilität ist ein zentrales Feature des Designs von C++. Wenn man sie eigentlich gar nicht benutzen darf, hätte man ja auch darauf verzichten können.

    Das ist so formuliert ja auch falsch. Die C-Kompatibilität war beim ursprünglichen Entwurf ein zentrales Feature des Designs von C++. Die daraus resultierenden Probleme werden von Stroustrup auch offen eingeräumt, aber damals war es für den Erfolg eben essentiell wichtig. Und dass man mich an der Stelle nicht falsch versteht: Es kann auch heute noch nützlich sein. Allerdings nicht für Code den man selbst schreibt, sondern zum Einbinden von C-Fremdbibliotheken.

    @onlinevideorecorder: Genau da kommen dann die sogenannten "C++-Killer" ins Spiel, die im Prinzip die gleiche Mächtigkeit wie C++ bieten wollen ohne den C-Krampf. Ob die nun D, Go oder Rust heißen. Die Idee ist gut, der Erfolg (leider) nicht. Denn diesen Sprachen fehlt das Ökosystem aus Tools, Frameworks und Bibliotheken, das C++ so erfolgreich macht. Und da liegt die Ironie bei der Sache: Genau weil C++ bei seiner Entstehung die alten C-Zöpfe nicht so konsequent abgeschnitten hat, deshalb konnte es überhaupt groß werden, und nun jeder Bemühung trotzen, es genau wegen dieser alten Zöpfe loszuwerden...

    kamakura schrieb:
    Dann hoffen wir mal, dass sie auch andere Programmierer nicht benutzen, ansonsten versteht man deren Code nicht.
    Stimmt. Hab ich persönlich allerdings auch noch nie gesehen (also jenseits simpler Konstantenersetzungen und Compiler-Switches). Was beweist, dass das ein übles Beispiel für overengineering ist.

    kamakura schrieb:
    Das Beispiel war an den Haaren herbeigezogen. Ansonsten wäre es nicht so kurz und leicht verständlich geworden. Objekt-Korruption und Heap-Korruption ist aber ein reales Problem. Realistische Beispiele findest du auf Stackoverflow:

    http://stackoverflow.com/search?q=heap+corruption+[c%2B%2B] (sorry, der Lima-URL-Tag kommt mit Brackets im Link nicht klar)

    Ich bestreite nicht, dass das ein reales Problem ist (habe selbst erst vor zwei Wochen einen ganzen Tag lang nach so einem Fehler suchen dürfen). Aber: Solche Fehler passieren nicht durch "Magie", sondern das Problem sitzt vor der Tastatur. In meinem Fall hat der Kollege es für eine gute Idee gehalten, einen static_cast zu benutzen. Was in der damaligen Klassenhierarchie funktioniert hat, in der aktuellen aber dazu führte, dass Daten an einen Member geschrieben wurden, den das Objekt gar nicht hatte. Explizite (und unsinnige) casts sind ja auch in deinen Beispielen oft das Problem, da gibt es also offenbar ein Muster...

    kamakura schrieb:
    Solche Bugs können jedem passieren, die sollte man also hoffentlich auch irgendwie debuggen können.

    Es ist vollkommen klar, dass man so etwas nicht debuggen kann. Ein expliziter Cast sagt dem Compiler ja gerade explizit, dass man sich einen Scheiß um seine Prüfungen und Warnungen kümmert. Entweder man ist sich sicher, dann braucht man keinen Debugger, oder man ist sich eben nicht sicher, dann macht man verdammt noch mal erst mal eine Typprüfung, auch wenns ein wenig "teurer" ist.

    kamakura schrieb:
    Nein, so war das nicht gemeint. Die Frage ist, wie das mit folgender deiner Aussagen zusammenpasst:
    Kurz:
    C, wenn du Betriebssysteme, Treiber, Maschinensteuerungen und andere Hardware-nahe Dinge programmieren willst.
    C++ für alles andere.

    Ach so. Ich sehe allerdings keinen Widerspruch. Da C eine Turing-vollständige Programmiersprache ist, sollte es selbstverständlich sein, dass man rein technisch gesehen nicht auf ein Anwendungsgebiet beschränkt ist. Es gibt allerdings ein typisches Anwendungsfeld. Und es gibt - aus welchen Gründen auch immer - natürlich immer Projekte, die daraus ausbrechen. Ich persönlich weiß zwar nicht warum man das tun sollte und Anwendungssoftware in C schreiben sollte. Aber bitte, es gibt ja auch Leute die lassen sich gern auspeitschen.


    Beitrag zuletzt geändert: 27.4.2016 20:07:24 von annihilus
  18. annihilus schrieb:
    kamakura schrieb:
    Hängende Referenzen: ...
    Unsichere smart pointer: ...

    Das ist aus dem gleichen Gruselkabinett wie dein voriges Vector-Beispiel: Den Karren mit 300 Klamotten sehenden Auges vor die Wand setzen und dann den Hersteller des Sicherheitsgurtes verklagen.
    Wenn ich von den sicher(er)en Mechanismen in C++ profitieren will, darf ich sie logischerweise nicht blöd auf C-Style-Zeiger casten, weil ich dann wenig gewonnen hab.
    Nur dass ich nirgends auf Zeiger gecastet habe. Du liest dir die Code-Beispiele anscheinend nicht mal durch.
    Nebenbei trotzdem besser als nichts: In deiner Referenz steht zwar Blödsinn (weil du explizit Blödsinn reingeschrieben hast), aber du kriegst keine Schutzverletzung, wie du sie mit einem Zeiger unweigerlich provoziert haben würdest.
    Es ist trivial, die Code-Beispiele umzuschreiben, dass es Schutzverletzungen gibt.
    #include <iostream>
    
    using namespace std;
    
    int main() {
        int* x = NULL;
        int& y = static_cast<int&>(*x);
    
        cout << "y = " << y << endl;
    
        return 0;
    }
    #include <iostream>
    #include <memory>
    
    using namespace std;
    
    int main () {
      auto x = make_unique<int>(-12345);
    
      cout << "x = " << *x << endl;
    
      auto y = move(x);
    
      cout << "x = " << *x << endl;
    
      return 0;
    }
    Aber was mich wirklich interessieren würde: Was um Gottes willen ist positiv daran, dass es keine Schutzverletzung gibt!?!?

    Z.B. ist der ganze Sinn von Smart Pointern ja diese zu provozieren, anstatt zu hängenden Zeigern zu werden (was auch nicht immer funktioniert, wie das Beispiel aus meinem letzten Post zeigte).
    kamakura schrieb:
    C war halt als minimalistische, Hardware-nahe, Compiler-freundliche, schnelle Sprache gedacht. Nicht als einfach verständliche.

    Ach was? War der Ausgangspunkt der ganzen Diskussion nicht genau der, dass du das Gegenteil behauptet hast? Von wegen zwei Bücher und so?
    Ne, es geht um C vs C++. Ich habe vor sechs Posts geschrieben:
    Ich habe nie gesagt, dass C eine einfach zu erlernende Sprache ist (nur im Vergleich zu C++).
    Und das Durcharbeiten der zwei Bücher K&R und van der Linden ist nicht ohne.
    Da habe ich mir geschenkt, tiefer drauf einzugehen, weils die gleiche Güteklasse ist: So etwas kann ich benutzen wenn ich gezwungen bin (meistens durch externe Gründe wie eine Bibliothek die ich benutzen muss), würde ich in C++ aber niemals einsetzen wenn ich eine Wahl habe.
    Wie verhinderst du denn Doppelinklusion dann? Wie würdest du denn Matrizen ohne mehrdimensionale Arrays realisieren?
    Das ist so formuliert ja auch falsch. Die C-Kompatibilität war beim ursprünglichen Entwurf ein zentrales Feature des Designs von C++. Die daraus resultierenden Probleme werden von Stroustrup auch offen eingeräumt, aber damals war es für den Erfolg eben essentiell wichtig. Und dass man mich an der Stelle nicht falsch versteht: Es kann auch heute noch nützlich sein. Allerdings nicht für Code den man selbst schreibt, sondern zum Einbinden von C-Fremdbibliotheken.
    Wie würdest du denn z.B. einen balancierten Baum ohne das C-Konstrukt Pointer in C++ implementieren?
    kamakura schrieb:
    Das Beispiel war an den Haaren herbeigezogen. Ansonsten wäre es nicht so kurz und leicht verständlich geworden. Objekt-Korruption und Heap-Korruption ist aber ein reales Problem. Realistische Beispiele findest du auf Stackoverflow:

    http://stackoverflow.com/search?q=heap+corruption+[c%2B%2B] (sorry, der Lima-URL-Tag kommt mit Brackets im Link nicht klar)

    Ich bestreite nicht, dass das ein reales Problem ist (habe selbst erst vor zwei Wochen einen ganzen Tag lang nach so einem Fehler suchen dürfen). Aber: Solche Fehler passieren nicht durch "Magie", sondern das Problem sitzt vor der Tastatur. In meinem Fall hat der Kollege es für eine gute Idee gehalten, einen static_cast zu benutzen. Was in der damaligen Klassenhierarchie funktioniert hat, in der aktuellen aber dazu führte, dass Daten an einen Member geschrieben wurden, den das Objekt gar nicht hatte. Explizite (und unsinnige) casts sind ja auch in deinen Beispielen oft das Problem, da gibt es also offenbar ein Muster...
    Aber wenn man in C Fehler macht, dann ist die Sprache schuld? :confused:

    Explizite casts muss man in C++ machen: Denk mal an die Implementierung von NULL in C als
    ((void *)0)
    .

    C++ erlaubt keine implizite casts von
    ((void *)0)
    auf jeden anderen Pointertyp, was ironischerweise zu viel mehr Unsicherheit führt. Bei so Ausdrücken wie
    while(cin >> x)
    muss stattdessen der operator void* oder operator bool überladen werden. In den alten Versionen lief so was noch:
    #include <iostream>
    
    using namespace std;
    
    int main(){
      cout << cin + 3*cin << endl;
      return 0;
    }
    clang++38 --std=c++03 doof.cpp -o doof
    ./doof
    4
    Irgendwann hieß es, man sollte dieses safe bool verwenden um derartiges zu vermeiden. Aber safe bool ist schon wieder obsolet, seit C++11 kann man explizite casts gesondert definieren und über die soll man es jetzt auch machen.

    Das soll einfacher als C sein?
    Es ist vollkommen klar, dass man so etwas nicht debuggen kann. Ein expliziter Cast sagt dem Compiler ja gerade explizit, dass man sich einen Scheiß um seine Prüfungen und Warnungen kümmert. Entweder man ist sich sicher, dann braucht man keinen Debugger, oder man ist sich eben nicht sicher, dann macht man verdammt noch mal erst mal eine Typprüfung, auch wenns ein wenig "teurer" ist.
    Ja, da bist du nicht auf dem neuesten Stand. Seit C++11 soll man ja gerade explizite Casts verwenden, es gibt nun eine Möglichkeit die speziell zu definieren.
    Und es gibt - aus welchen Gründen auch immer - natürlich immer Projekte, die daraus ausbrechen. Ich persönlich weiß zwar nicht warum man das tun sollte und Anwendungssoftware in C schreiben sollte. Aber bitte, es gibt ja auch Leute die lassen sich gern auspeitschen.
    Das ist eine bisschen dürftige Erklärung.
  19. kamakura schrieb:
    Nur dass ich nirgends auf Zeiger gecastet habe.

    Entschuldigung, mein Fehler. War eine Referenz. Das ist natürlich viel besser.

    kamakura schrieb:
    Es ist trivial, die Code-Beispiele umzuschreiben, dass es Schutzverletzungen gibt.
    [...]

    Nice! :)
    Dein Skill für Horrorcode nötigt mir fast Respekt ab.
    Ich verstehe nur immer noch nicht, was du damit eigentlich beweisen willst. Dass man etwas kaputtmachen kann, wenn man es unbedingt kaputtmachen will, ist als Erkenntnis ebensowenig neu wie spektakulär.

    kamakura schrieb:
    Aber was mich wirklich interessieren würde: Was um Gottes willen ist positiv daran, dass es keine Schutzverletzung gibt!?!?

    Naja, ob ein komplett unsinniger Wert oder ein Absturz "besser" ist, hängt ein wenig vom Anwendungsfall ab. Und das ist bei deinen Beispielen schwer zu beurteilen, weil es für die schlicht keinen Anwendungsfall gibt.

    kamakura schrieb:
    Z.B. ist der ganze Sinn von Smart Pointern ja diese zu provozieren, anstatt zu hängenden Zeigern zu werden

    Äh nein, der Sinn von Smart Pointern ist, möglichst beides von vornherein zu vermeiden.

    kamakura schrieb:
    (was auch nicht immer funktioniert, wie das Beispiel aus meinem letzten Post zeigte).

    So wie Kondome nicht funktionieren wenn ich Löcher reinsteche. Heißt nicht dass das Konzept vom Grundsatz her schon blödsinnig ist. :P
    Nochmal, das Beispiel zeigt gar nichts außer dass die Datenkapselung einer Klasse nicht funktioniert, wenn man sie aufbricht und reingreift. Was ebensowenig überraschend wie erhellend war.

    kamakura schrieb:
    Da habe ich mir geschenkt, tiefer drauf einzugehen, weils die gleiche Güteklasse ist: So etwas kann ich benutzen wenn ich gezwungen bin (meistens durch externe Gründe wie eine Bibliothek die ich benutzen muss), würde ich in C++ aber niemals einsetzen wenn ich eine Wahl habe.
    Wie verhinderst du denn Doppelinklusion dann? Wie würdest du denn Matrizen ohne mehrdimensionale Arrays realisieren?

    Wie schon gesagt sind das Fälle, die mich im Programmieralltag kaum berühren. Über ein simples
    #pragma once
    in jedem Header muss man nicht groß nachdenken, wenn man (insbesondere als Anfänger) das nicht will.
    Und was erst die Matrizen angeht... wenn ich wiederholt und performancekritisch in meinem Programm mehrdimensionale Felder benötige... dann entwickele ich genau die Art von Anwendung, für die ich ohnehin die Verwendung von C nahegelegt habe.
    In allen anderen Fällen spricht überhaupt nichts dagegen, generische Listen oder Maps (sei es aus std, boost, Qt oder was auch immer) zu schachteln. Wenn Performance-Fetischisten bei der Vorstellung einen Infarkt erleiden ist mir das relativ schnurz, I just work here.

    kamakura schrieb:
    Wie würdest du denn z.B. einen balancierten Baum ohne das C-Konstrukt Pointer in C++ implementieren?

    Gar nicht. Du liest nicht was ich schreibe oder verstehst es nicht. Es spricht überhaupt nichts gegen die Verwendung von Pointern in C++, solange man die vernünftig in einer Klasse kapselt und mit RAII absichert.
    Insbesondere gebe ich keinen Zeiger auf einen Baumknoten nach "draußen" und wundere mich dann dass mir das meine Struktur zerschießen kann, wie du das hier ständig praktizierst.

    kamakura schrieb:
    Aber wenn man in C Fehler macht, dann ist die Sprache schuld? :confused:

    Nein, es gilt selbstverständlich immer das "garbage in, garbage out"-Prinzip. Es gibt halt nur Sprachen, die gewisse Arten von Fehlern viel krasser provozieren als andere. Und ja, zu denen gehört C und ganz entschieden auch C++, insbesondere wenn ich es nicht wie C++ benutze sondern wie "C mit Klassen".

    kamakura schrieb:
    int main(){
      cout << cin + 3*cin << endl;
      return 0;
    }
    clang++38 --std=c++03 doof.cpp -o doof
    ./doof
    4

    Ich gebe unumwunden zu, ich habe keine Ahnung worauf du hier hinaus willst. Könnte auch daran liegen dass ich im Leben noch kein cin gebraucht habe.

    kamakura schrieb:
    Ja, da bist du nicht auf dem neuesten Stand. Seit C++11 soll man ja gerade explizite Casts verwenden, es gibt nun eine Möglichkeit die speziell zu definieren.

    Will ich nicht ausschleßen, dass ich da nicht up to date bin. Wenn du mir eine Quelle oder einen Link nennen könntest, wo genau im C++11-Standard ungeprüfte statische Casts als gute Praxis empfohlen werden, das würde ich in der Tat gerne sehen.

    kamakura schrieb:
    Und es gibt - aus welchen Gründen auch immer - natürlich immer Projekte, die daraus ausbrechen. Ich persönlich weiß zwar nicht warum man das tun sollte und Anwendungssoftware in C schreiben sollte. Aber bitte, es gibt ja auch Leute die lassen sich gern auspeitschen.
    Das ist eine bisschen dürftige Erklärung.

    Diese Meinung sei dir unbenommen. Ich persönlich weiß nicht, was daran dürftig sein soll. String- und Containerklassen (um nur zwei Beispiele zu nennen) sind nunmal sehr komfortabel, un generell sind Klassen ein guter (wenn natürlich auch nicht der einzige Weg), Code zu strukturieren und zu modularisieren. Wer darauf verzichtet, muss doch Gründe dafür haben. Meistens wird der Performance-Unterschied genannt. Dieser ist aber nunmal nicht so entscheidend, dass sich der Tradeoff lohnt - es sei denn, ich bewege mich in denen von mir genannten "klassischen" C-Anwendungsgebieten.
  20. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    kamakura schrieb:
    @hackyourlife: was hat die verlinkte Datei für eine Grammatik? Definitiv nicht yacc. Und dass nur das typedef ein Problem macht, steht sogar in den Comments (ganz oben) der verlinkten Datei.
    Wie zu erwarten war, hat diese Datei die Grammatik »Attributierte EBNF«. Im Speziellen handelt es sich um eine Grammatik-Beschreibung für den Generator Coco/R. Dass du den nicht kennst wundert mich übrigens nicht.

    Zum Problem mit dem typedef: hast du denn auch nur annähernd verstanden, was dir der Kommentar in der Datei sagen will? Sieht nicht so aus, denn sonst wüsstest du, um was es sich bei einem »LL(1)-Konflikt« handelt, und dass das nichts mit kontextsensitiv/kontextfrei zu tun hat. Du leitest mit den LL(1)-Resolvern den Parser lediglich in eine konkrete Regel, um die Uneindeutigkeit (= mehrere Regeln beginnen mit dem selben Token) zu eliminieren. Denn das ist das einzige Problem mit dem typedef hier. Würdest du beim Parsen einen GLR-Parser nutzen (kann ebenfalls nur CFGs parsen), dann hättest du nicht einmal ein Problem mit LL(k)-Konflikten. Für die Sache mit dem typedef wirst du aber wohl selbst dann keinen eindeutigen Parse-Baum bekommen. Dass eine Grammatik nicht eindeutig ist, darf sein, hat aber nichts mit der Klasse der Grammatik zu tun. Ein weiteres Beispiel für uneindeutige Konstrukte ist übrigens z.B. das dangling else, und dort wirst du wohl auch nicht auf die Idee kommen zu behaupten, dass das die Klasse der Grammatik irgendwie berührt.

    Wenn wir schon dabei sind:
    CFG: A → xBy
    Wenn du dir nun die verlinkte Grammatik ansiehst, wirst du feststellen, dass du ganz ohne Resolvern immer noch eine CFG hast (weil immer noch alle Regeln von der Form A → … sind). Nur kannst du die halt nicht mehr mit einem rekursiven Abstieg sinnvoll parsen.

    Und unabhängig davon kann man, wenn man schon Syntax und Semantik trennt, diese Trennung sehr willkürlich wählen und damit praktisch immer eine CFG erhalten. Die Praxisrelevanz deines Beitrages zum Thema »Grammatik« ist also sowieso von vornherein mit 0 zu bewerten. Einzig, dass C++ deutlich komplexer zu parsen ist, ist richtig und hervorzuheben.

    annihilus schrieb:
    Und was erst die Matrizen angeht... wenn ich wiederholt und performancekritisch in meinem Programm mehrdimensionale Felder benötige... dann entwickele ich genau die Art von Anwendung, für die ich ohnehin die Verwendung von C nahegelegt habe.
    In allen anderen Fällen spricht überhaupt nichts dagegen, generische Listen oder Maps (sei es aus std, boost, Qt oder was auch immer) zu schachteln. Wenn Performance-Fetischisten bei der Vorstellung einen Infarkt erleiden ist mir das relativ schnurz, I just work here.
    … was natürlich nicht heißt, dass man bewusst und absichtlich unsinnig ineffizienten Code bauen sollte. Dafür gibt es schließlich besser geeignete Sprachen :-P

    Die C-Kompatibilität war beim ursprünglichen Entwurf ein zentrales Feature des Designs von C++. Die daraus resultierenden Probleme werden von Stroustrup auch offen eingeräumt, aber damals war es für den Erfolg eben essentiell wichtig. Und dass man mich an der Stelle nicht falsch versteht: Es kann auch heute noch nützlich sein. Allerdings nicht für Code den man selbst schreibt, sondern zum Einbinden von C-Fremdbibliotheken.
    Wenigstens hat C eine brauchbare Kompatibilität. Bei C++ hast du ja schon das Problem, dass eine Bibliothek, die mit einem Compiler A erzeugt wurde, nicht unbedingt mit einem anderen Compiler B benutzt (= dagegen gelinkt) werden kann. Ob das in der Praxis ein Problem ist oder nicht sei dahingestellt.

    Genau da kommen dann die sogenannten "C++-Killer" ins Spiel, die im Prinzip die gleiche Mächtigkeit wie C++ bieten wollen ohne den C-Krampf. Ob die nun D, Go oder Rust heißen. Die Idee ist gut, der Erfolg (leider) nicht. Denn diesen Sprachen fehlt das Ökosystem aus Tools, Frameworks und Bibliotheken, das C++ so erfolgreich macht. Und da liegt die Ironie bei der Sache: Genau weil C++ bei seiner Entstehung die alten C-Zöpfe nicht so konsequent abgeschnitten hat, deshalb konnte es überhaupt groß werden, und nun jeder Bemühung trotzen, es genau wegen dieser alten Zöpfe loszuwerden...
    Wie es scheint, wächst da gerade mal wieder was neues heran, was verspricht, sowohl C-Bibliotheken zu unterstützen, als auch »sichere« Sprachen wie Java/Scala/Python/…, mit der Möglichkeit, diese Sprachen perfekt mischen zu können, ohne Performance-Verluste an der Sprachgrenze und ohne umständlichen Foreign Language-APIs. Sollte das tatsächlich etwas werden, hätte das wohl sogar recht schnell große Verbreitung, handelt es sich doch dabei um eine Weiterentwicklung der durchaus verbreiteten Java VM. Und spätestens, wenn das was wird, muss man sich hoffentlich weniger mit C++ o.ä. herumnerven.
  21. hackyourlife schrieb:
    … was natürlich nicht heißt, dass man bewusst und absichtlich unsinnig ineffizienten Code bauen sollte. Dafür gibt es schließlich besser geeignete Sprachen :-P

    Das ist eben, was mich an solchen Argumentationen immer ärgert. Ja, Containerklassen haben (logischerweise) gegenüber der minimalistischen Array-Lösung mehr Overhead. Aber nein, das macht sie nicht sofort "unsinnig ineffizient"! Tatsächlich, und das war mein Argument, wird man den Unterschied im Regelfall nicht mal merken, wenn man nicht gerade mit hunderten von Matrizen jonglieren muss... und das muss eine Anwendung in der Regel einfach nicht.
    Hier überwiegt meiner Ansicht nach dann ganz klar der Vorteil der komfortableren Anwendbarkeit und Sicherheit.
    Wer immer und überall der Geschwindigkeit absolute Priorität einräumt kann auch gleich in Assembler entwickeln.

    hackyourlife schrieb:
    Wie es scheint, wächst da gerade mal wieder was neues heran, was verspricht, sowohl C-Bibliotheken zu unterstützen, als
    auch »sichere« Sprachen wie Java/Scala/Python/…, mit der Möglichkeit, diese Sprachen perfekt mischen zu können, ohne Performance-Verluste an der Sprachgrenze und ohne umständlichen Foreign Language-APIs. Sollte das tatsächlich etwas werden, hätte das wohl sogar recht schnell große Verbreitung, handelt es sich doch dabei um eine Weiterentwicklung der durchaus verbreiteten Java VM. Und spätestens, wenn das was wird, muss man sich hoffentlich weniger mit C++ o.ä. herumnerven.

    Igitt, er hat Java VM gesagt! So ein Rotz kann doch nur unsicher und langsam sein! :)
    Spaß beiseite, von so manchem C- oder C++-Entwickler wirst du diesen Einwand garantiert hören.
    Und ganz generell: Selbst wenn diese oder eine beliebige andere neue Sprache das objektiv beste auf Gottes grüner Wiese wäre, wäre das noch lange kein Garant für Erfolg. Ich mein, es gibt hunderte von Programmiersprachen. Lässt man Vertreter wie Intercal, Shakespeare, Brainfuck etc. mal außen vor, haben die Entwickler diese doch nicht aus Spaß entworfen, sondern weil sie das neue System für besser hielten als die bestehenden (und sei es auch nur für eine bestimmte Einsatz-Sphäre). Wie viele Sprachen haben heute eine wirklich nennenswerte Verbreitung? Vielleicht 5-10. Manche davon sind, nüchtern betrachtet, so schlecht entworfen, dass man nur den Kopf schütteln kann. Man nehme mal PHP. Das zeigt eindeutig, dass man fast beliebig scheiße sein und trotzdem eine Riesen-Fangemeinde haben kann. Quasi der Justin-Bieber-Effekt der Programmiererwelt. Umgekehrt fristet so manche richtig gut entworfene Sprache ein totales Nischendasein, da als akademisch verschrien oder praktisch unbenutzbar aufgrund fehlender Tools und Bibliotheken. Oder kennt hier irgend eine Sau vielleicht Oberon?

    Wenn mich in einem Thread wie genau diesem hier vor 15 Jahren jemand gefragt hätte, was meiner Ansiicht nach die perfekte Einsteiger-Sprache ist, hätte ich ohne eine Sekunde nachzudenken "Pascal" gesagt. Die Sprache ist heute nicht weniger geil, da aber so gut wie niemand mehr Pascal (oder Delphi) verwendet, ist einem als Einsteiger immer bewusst, dass man früher oder später umsatteln muss - und fragt sich natürlich, ob man dann nicht gleich C oder C++ lernen könnte. Und wie ich schon mehrmals geschrieben habe, halte ich gerade diese Sprachen für enorm einsteigerfeindlich. Angesichts dieser Tatsache antworte ich auf die Frage heutzutage meistens "C#". Richtig happy macht mich das nicht. Nichts würd mich mehr freuen, als wenn es bald mal wieder eine Sprache gäbe, die man guten Gewissens jedem Anfänger empfehlen kann.
  22. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!