Warum verwendet ueberhaupt noch irgendjemand C?



  • Dobi schrieb:

    @Marthog: Naja, man könnte sich ja eine Sprache vorstellen, die zwar at runtime langsamer ist, aber dafür
    - durch ein strengeres Typsystem zu noch mehr Genauigkeit zwingt
    - keine memleaks zulässt
    - nicht erlaubt über arraygrenzen hinauszulatschen
    - den edit-Compile-test-cycle nicht so in die Länge zieht, dass man zwischendurch immer wieder aus Langeweile ins Forum guckt
    - weniger legacy-Fallstricke hat
    - usw.
    Dann könnte man eventuell ja doch in weniger Zeit mit fehlerfreien features rauskommen. Ähnlich wie C++ einem bei vielem hilft, was bei C nervig ist, könnte eine solche Sprache einen ja noch mehr von den low-leveligen Details befreien. 🙂

    So eine Sprache haette ich sehr gerne, allerdings sind die einzigen beiden Sprachen, die die Bedingungen erfuellen und mir persoenlich zusagen Haskell und Rust. Fuer Haskell ist es mir oft zu viel Aufwand, alles funktional auszudruecken, besonders wenn man mit Dateiformeten oder grafischer Ausgabe hantiert und Rust bietet noch keine Garantie fuer Langzeitsupport. 😞

    P.S. Langsamer muessen sie gar nicht mal sein, weil ein strikteres System mehr Optimierungen zulaesst.



  • Dobi schrieb:

    volkard schrieb:

    Und die, die man brauchen kann, sind in jeder Sprache produktiv, aber man tut gut daran, ihnen C++ zu geben, weils damit schnell geht und einfach wenig Fehler ausgeliefert werden.

    Bezieht sich das jetzt nur auf den Vergleich mit C oder auch auf andere Sprachen? Weil generell würd ich schätzen, gehört C++ ja schon eher auch zu den Sprachen, bei denen man Entwicklerzeit opfert um CPU-Zeit zu sparen. Und ich habe den Eindruck, dass man viele Projekte, bei denen Performance ziemlich egal ist, mit weniger Entwicklungsaufwand fehlerfreier in anderen Sprachen umsetzen kann. Meinst du nicht?

    Ich beziehe mich insbesondere auf die Skriptsprachen, mit denen man ein Projekt anfängt und es sofort unerweiterbar ist.
    Fehlerfreiheit als Designziel kommt beim Lesen von Struppi&Meyers doch bärenstark rüber. Die Sprache ist genau dafür gemacht. Daß man dafür nichtmal Laufzeit ausgeben muss, ist elend prima. Und ein Marketing-Nachteil(!!!), wenn ich Dich so höre. "Nur bittere Medicin kann gut sein." "Wenn man nichts dafür bezahlz, kann es auch nichts taugen."…



  • @volkard: OK, Fehlerfreiheit als Designziel kommt besonders in den Effektive-Büchern sehr gut rüber, finde ich auch.
    Nur habe ich den Eindruck, dass es noch viel besser/schicker gehen müsste.
    Wenn es das dann auch noch ohne Laufzeitkosten gibt, umso besser. Mit C++ gewinnt man ja auch vieles an Sicherheit/Einfachheit gegenüber C ohne dass es dadurch langsamer wird.

    Den Geschwindigkeitsverlust hatte ich nur erwähnt, weil ich oft die Performance als einziges Argument für C++ gegenüber anderen Sprachen höre. Und das finde ich bei vielen Anwendungen fehl am Platz.

    In welcher Sprache man nun sicherer/einfacher programmieren kann, ist natürlich auch Geschmacks-/Gewöhnungssache. Ich merke nur bei mir, dass ich obwohl ich in C++ mit Abstand die meiste Erfahrung habe und das meiste drüber gelesen habe, mich mittlerweile in Python, Haskell und Elm irgendwie produktiver fühle.



  • Dobi schrieb:

    @Marthog: Naja, man könnte sich ja eine Sprache vorstellen, die zwar at runtime langsamer ist, aber dafür
    - durch ein strengeres Typsystem zu noch mehr Genauigkeit zwingt

    Hä? NOCH mehr? Wann isses Dir zum letzten mal vorgekommen, daß strengere Typen Dir einen wichtigen Fehler aufgedeckt hätten? Ich grüble gerade und kein Fall fällt mir ein.

    Dobi schrieb:

    - keine memleaks zulässt

    Mädel, memleaks kommen doch in C++ bereits nicht mehr vor. Seit Jahrzehnten übrigens. Für diese Sicherheit muss man keine Laufzeitkosten eingehen.

    Dobi schrieb:

    - nicht erlaubt über arraygrenzen hinauszulatschen

    dito nebst facepalm

    Dobi schrieb:

    - den edit-Compile-test-cycle nicht so in die Länge zieht, dass man zwischendurch immer wieder aus Langeweile ins Forum guckt

    dito. Ich kann Dir sagen, wo man einen i7 mit 16G kauft und SSD kauft. Wenn Du damit noch Sorgen hast, liegt der Fehler bei Dir.

    Dobi schrieb:

    - weniger legacy-Fallstricke hat

    Jo, die Kompatibilität mit altem Code ist das Riesenproblem.

    Dobi schrieb:

    @Ethon: Ja, oder außerhalb des "kingdom of nouns" dann halt C#, Clojure, D, F#, Go, Haskell, Lisp, Python, Ruby, Rust oder Scala. 😉
    Na gut, die Hälfte fliegt natürlich für viele direkt raus, weil dynamische Typisierung ja angeblich für große Projekte nix taugt, übrig bleiben ja trotzdem noch welche. 🤡

    Hauen wir netterweise auch noch Sprachen weg, in denen man RAII nicht machen kann. Wor wollten doch typische Aus-Versehen-Fehler ein wenig vermeiden.



  • Dobi schrieb:

    @volkard: OK, Fehlerfreiheit als Designziel kommt besonders in den Effektive-Büchern sehr gut rüber, finde ich auch.
    Nur habe ich den Eindruck, dass es noch viel besser/schicker gehen müsste.

    Jo, die Rustikusse haben den (guten und notwendigen) Anfang gemacht. Leider weit am Ziel vorbei.
    Unnötig weit von der Hardware entfernt.
    Mystisches Patternmatching ohne daß ich auch nur entfernt einsehen könnte, welchen Sinn das Sprachmittel. Proggern wie in Prolog? Ballmer-Peak nicht getroffen sag ich da mal.
    Templates abgelöst durch Makros, die doch dann viel zu schwach sind.

    Naja, ich hab ja Zeit. Noch schnell 10-20 Rust-Nachfolger abwarten und dann wird einer dabei sein, der was taugt. Der wird sich aber nicht durchsetzen, es wird kaum Libs geben.



  • Puh, weiß nicht. Ich könnte mir jetzt irgendwas mit impliziten Konvertierungen zusammenspinnen, aber das wär albern.

    Typenmäßig fehlen mir halt noch ganz andere, nicht unbedingt nur Strenge, sondern auch sowas wie ADTs, pattern matching usw.

    Mir wird mein C++-Code oft einfach viel zu lang. Vor Kurzem hatte ich ein Optimierungsproblem zu lösen. Als ich den Prototyp von Haskell nach C++ portiert habe, wurde der Code ca. 4 mal so lang und für meinen Geschmack tausendmal hässliger. Schon allein was man für Syntax-Verrenkungen für higher order functions machen muss ...
    Aber gut, jetzt bin ich weg von Typen und bei Geschmack angekommen. 😉

    Ich habe es leider teilweise mit Code zu tun, der auch jetzt nach Jahrzehnten noch memleakt. 😕

    Man kann auch mit std::vector Iteratoren Mist bauen, der im release umbemerkt übers Array latscht ohne irgendwas zu schmeissen.

    SSD wird mal Zeit bei mir, ja. Aber ein Projekt, für das jetzt über 5 Minuten "code generiert" wird, wird dann ja vermutlich auch nicht plötzlich innerhalb von 2 Sekunden fertig sein.

    Ob RAII jetzt unbedingt notwendig ist, oder ob es mit GC oder anders nicht noch bessere Möglichkeiten gibt, solche Fehler zu vermeiden, kann ich nicht beurteilen.

    Aber gut, im C++-Forum über C++ zu meckern ist wahrscheinlich eh nicht so geschickt von mir. 🙂



  • Dobi schrieb:

    Mir wird mein C++-Code oft einfach viel zu lang. Vor Kurzem hatte ich ein Optimierungsproblem zu lösen. Als ich den Prototyp von Haskell nach C++ portiert habe, wurde der Code ca. 4 mal so lang und für meinen Geschmack tausendmal hässliger.

    Mir geht andersrum.

    Dobi schrieb:

    Ich habe es leider teilweise mit Code zu tun, der auch jetzt nach Jahrzehnten noch memleakt. 😕

    Ok. Sagen wir mal so: Dass der Wolf C++-Bücher schreibt, sollte man nicht der Sprache anlasten.
    Vor fast 10 Jahren war das Problem schon seit mehr als 10 Jahren weg.
    http://www.c-plusplus.net/forum/158841-42
    Eigentlich war es immer ein Problem anderer Leute.

    Dobi schrieb:

    Man kann auch mit std::vector Iteratoren Mist bauen, der im release umbemerkt übers Array latscht ohne irgendwas zu schmeissen.

    Wie macht Ihr das? Machst Du sowas oder konstruoerst Du nur gerade ein Problem? ALso ich mache sowas nicht.

    Dobi schrieb:

    SSD wird mal Zeit bei mir, ja.

    100€
    Entwicklungsrechner ohne SSD, mag mir ja gar nicht den Prozessor vorstellen.
    So langsam sollte es auch gebrauchte SSDs geben von Leuten, die ihre alte (kleine oder lahme SSD) rauswerfen. 🕶 💡

    Dobi schrieb:

    Aber ein Projekt, für das jetzt über 5 Minuten "code generiert" wird, wird dann ja vermutlich auch nicht plötzlich innerhalb von 2 Sekunden fertig sein.

    *lach*
    Linux-Kernel in 90 Sekunden.
    Ja, man KANN auch 200 Dateien schreiben, die länger brauchen als andere 20000, man muss nur in jeder Datei die <windows.h> und die "std-all.h" inkludieren.

    Dobi schrieb:

    Aber gut, im C++-Forum über C++ zu meckern ist wahrscheinlich eh nicht so geschickt von mir. 🙂

    Ja, ist lästig, wenn jemand widerspricht, der sich im angemeckerten Thema ein wenig auskennt. 🤡



  • Ich hab hier alten Code rumliegen, der viel mit Iteratoren rum"trickst" anstatt einfach den Kram aus <algorithm> zu verwenden. Und da ist sowas schonmal passiert. Schlimm ist ebenso, dass der teiweise von mir ist. ; )
    Und wenn man mal wochenlang mit immer mehr Logging, core-dumps usw. hinter sowas beim Kunden hergerannt ist, bis man es endlich gefunden hatte, hinterlässt das halt seelische Wunden. : D

    Warum unsere Projekte hier so ewig kompilieren, weiß ich nicht. Ich werds aber mal mit einer SSD probieren. 👍

    Gegens Widersprechen hab ich überhaupt nix. Vorallem nicht wenn du das machst, weil ich den Eindruck habe, dass du mehr Ahnung hast als ich, wodurch ich dabei etwas lernen kann. Ich meinte eher, dass ich nicht will, dass sich jemand (z.B. du) wegen meiner Posts ärgern muss. : (



  • volkard schrieb:

    Datenkapselung ist irrelevant. Kennst Du die Members vom FILE?
    Datenkapselung ganz leicht nachzubauen. Einfach die Members mit priv_ anfangen lassen.

    Deine Idee funktioniert nur dann wenn die Bedeutung des priv_ nicht vergessen wird und eine Doku dazu vorhanden ist, damit auch andere die Bedeutung sicher deuten (und dies nicht als priviliged Member verstehen). Greife ich aber schreibend darauf zu, bekomme ich keine Fehlermeldung.

    Mit C++ kann man das besser machen. Ein private und peng kommt es bei einem schreibenden Zugriff zu einem Compilerfehler. Aus einer Assertion im Doc wird eine richtige Assertion. Und das liebe ich daran. Man kann etwas strikter seine Entscheidungen implementieren.

    Etas ähnliches ist es auch beim Zugriff auf Zeiger? Soll ich diese auf NULL prüfen? Oder immer != NULL annehmen?

    Natürlich kann man damit Entwickler, mit Drang sich selbst ins Bein zu schießen, nicht stoppen.

    ---

    Kennst Du die Members vom FILE?

    Nö, aber ich weis wo ich diese finde.

    Das FILE Objekt hat bei mir nur deswegen funktioniert, da man ja nur Zeiger auf FILE Objekte nutzt und ich so von einem Handle Objekt ausging.


  • Mod

    Bitte ein Bit schrieb:

    Kennst Du die Members vom FILE?

    Nö, aber ich weis wo ich diese finde.

    Bist du da sicher? Die stehen nämlich nicht einfach in stdio.h (zumindest sollten sie nicht) und sind nicht von normalem Anwendungscode aus ansprechbar. Egal ob sie priv_ am Anfang haben oder nicht.



  • Dobi schrieb:

    Ob RAII jetzt unbedingt notwendig ist, oder ob es mit GC oder anders nicht noch bessere Möglichkeiten gibt, solche Fehler zu vermeiden, kann ich nicht beurteilen.

    Mit den heutigen GCs jedenfalls nicht. Das Hauptproblem ist nicht das GCs langsamer sind oder dass man keine Kontrolle mehr darüber hat wann die laufen, sondern dass aktuelle Implementierungen einfach keine deterministischen Destruktoren zulassen. Dann leakt zwar kein Speicher mehr, dafür aber alles andere.

    Bitte ein Bit schrieb:

    Ein private und peng kommt es bei einem schreibenden Zugriff zu einem Compilerfehler.

    FTFY



  • Joa, aber irgendwie bekommt man es ja auch in GC-Sprachen hin. Klar, sowas hier

    with open('workfile', 'r') as f:
        read_data = f.read()
    

    ersetzt RAII nicht wirklich, aber zumindest hab ich in Python und auch Haskell dem bisher noch nicht nachgeweint.



  • Bitte ein Bit schrieb:

    Mit C++ kann man das besser machen. Ein private und peng kommt es bei einem schreibenden Zugriff zu einem Compilerfehler. Aus einer Assertion im Doc wird eine richtige Assertion. Und das liebe ich daran. Man kann etwas strikter seine Entscheidungen implementieren.

    lol. Wenn ich meine Member priv_XYZ nenne, dann ist jedem Programmierer offensichtlich, dass das private Member sind. Wer dennoch drauf zugreift, der macht das bewusst.

    Die Leute, die mutwillig auf priv_XYZ zugreifen kannst du auch mit C++ nicht aufhalten. Sei es durch "#define private public", durch Template-Hacks, ODR-Verletzungen oder einfach char*-Fummeleien, 100% Sicherheit erreichst du nicht. Ist aber auch völliger Overkill.

    Dobi schrieb:

    Joa, aber irgendwie bekommt man es ja auch in GC-Sprachen hin. Klar, sowas hier

    with open('workfile', 'r') as f:
        read_data = f.read()
    

    ersetzt RAII nicht wirklich, aber zumindest hab ich in Python und auch Haskell dem bisher noch nicht nachgeweint.

    In Haskell:

    withFile "test.txt" ReadMode $ \handle -> do
      data <- hGetContents handle
    

    Im Gegensatzt zu Python kann man hier das with gar nicht vergessen, weil withFile eine Funktion (Lambda) als zweites Argument erwartet. Insofern sehe ich hier überhaupt keinen Nachteil gegenüber RAII.



  • @Dobi Das sieht ja ganz hübsch aus, aber was passiert wenn ich jetzt mehrere solcher Dateien gleichzeitig öffnen, oder sogar in einen Container stecken will?



  • Wüsste nicht, wozu man das braucht, aber hier mal eine Implementation in Haskell:

    withFiles :: [FilePath] -> IOMode -> ([Handle] -> IO r) -> IO r
    withFiles []     m f = f []
    withFiles (x:xs) m f = withFile x m $ \h -> withFiles xs m $ \hs -> f (h:hs)
    
    main = withFiles ["1.txt","2.txt"] ReadMode $ \hs ->
             forM_ hs $ \h -> do
               d <- hGetContents h
               putStrLn d
    


  • Bist du da sicher? Die stehen nämlich nicht einfach in stdio.h (zumindest sollten sie nicht) und sind nicht von normalem Anwendungscode aus ansprechbar. Egal ob sie priv_ am Anfang haben oder nicht.

    Also wenn ich im Visual Studio auf FILE gehe und ein Goto Definition mache (F12), komme ich an direkt in die Struct Defintion in stdio.h.

    Unter Codelite komme ich nach einer etwas unwesentlich längeren Suche auch auf das struct in stdio.h. Bin da zuerst in cstdio namespace Deklaration gelandet.

    Und wenn ich File-> eintippe, listet mir Intellisense automatisch die ganzen Member auf.

    lol. Wenn ich meine Member priv_XYZ nenne, dann ist jedem Programmierer offensichtlich, dass das private Member sind. Wer dennoch drauf zugreift, der macht das bewusst.

    Und das bezweifele ich. Erstens steht nicht immer eine saubere Doku da. Und zweitens sind Präfixe selten eindeutig und deren Bedeutung gehen schon einmal vorloren. Wer achtet denn schon immer auf eine intelligente Variablenbezeichnug?

    Und dann kommt ein C Programmierer durch und durch, hat keine Ahnung von private Membern, und greift einfach darauf zu, weil er die Bedeutung von private nicht kennt.

    Ist das bewusst?



  • pragmatiker schrieb:

    Wenn du ein Softwareprojekt in C anfängst, bekommst du Pragmatiker und das Projekt geht vorwärts.
    Wenn du ein Softwareprojekt in C++ anfängst, bekommst du übergeschnappte Template-Fanatiker und die Programmierer verfangen sich in Design-Überlegungen und bauen unnötige Bibliotheken. Nichts geht mehr vorwärts. Nenn mir mal ein grösseres Software-Projekt, das alle Regeln von STL befolgt.

    C++ ist gut, wenn man pragmatisch bleibt und nicht übermütig in der Nutzung der Sprachfeatures wird. Aber die Richtung von STL ist gefährlich, so wird man bestenfalls Library-Developer.

    C++ kann schon ein Fass ohne Boden sein. Seine Anwendung erfordert ein Höchstmaß an Disziplin und Erfahrung. Sonst sprengt man sich schnell ein Bein weg (Stroustrup).


Anmelden zum Antworten