The "C is Efficient" Language Fallacy



  • das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind (bei dem tippfehler-beispiel) und einen davon von vorn herein weglassen. optimierungen zur laufzeit sind dazu noch nicht mal nötig.

    Ich ergänze: dass hier nichts optimiert werden kann, was es nicht in C++ auch kann.



  • Shade Of Mine schrieb:

    Java hat sogar nur Call By Value - ein Call By Reference gibt es garnicht 🙄

    Genau das sagte ich doch...

    asc schrieb:

    Rein Optisch sieht es bei der Methode clear für mich wie eine Wertübergabe unter C++ aus. Dennoch kann man Änderungen wie bei einer C++ Referenz machen. Tatsächlich ist es aber eher ein Zeiger der kopiert wird, so das ein new an der Stelle tatsächlich keine Außenwirkung hat.

    Richtig. Trotzdem ein lupenreines call-by-value Beispiel.

    Ich persönlich finde das Verhalten (sowohl unter Java als auch C#) verwirrend. Ich weiß nicht mehr ob man in Java eigene Werttypen (was in C# definitiv geht) definieren kann, sehe es aber als Problematisch an, wenn man für einen Parameter erst bei der Betrachtung des Typen weiß, ob eine Änderung an diesem das Original ändert oder nicht.

    In Java ist das sauber gelöst. Von Primitiven abgesehen (die eh immutable sind) , gibt es keine Wertobjekte.
    In C# ist das anders: http://www.geocities.com/csharpfaq/structs.html



  • asc schrieb:

    Rein Optisch sieht es bei der Methode clear für mich wie eine Wertübergabe unter C++ aus. Dennoch kann man Änderungen wie bei einer C++ Referenz machen.

    du hast zuviel in C programmiert. vielleicht hilfts dir, wenn du dir vorstellst, dass java-referenzen sowas wie pointer sind.

    JustAnotherNoob schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind (bei dem tippfehler-beispiel) und einen davon von vorn herein weglassen. optimierungen zur laufzeit sind dazu noch nicht mal nötig.

    Ich ergänze: dass hier nichts optimiert werden kann, was es nicht in C++ auch kann.

    rischtich, allerdings kann die Java-VN noch zur laufzeit optimieren (und tut dies oft auch).
    🙂



  • +fricky schrieb:

    asc schrieb:

    Rein Optisch sieht es bei der Methode clear für mich wie eine Wertübergabe unter C++ aus. Dennoch kann man Änderungen wie bei einer C++ Referenz machen.

    du hast zuviel in C programmiert. vielleicht hilfts dir, wenn du dir vorstellst, dass java-referenzen sowas wie pointer sind.

    JustAnotherNoob schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind (bei dem tippfehler-beispiel) und einen davon von vorn herein weglassen. optimierungen zur laufzeit sind dazu noch nicht mal nötig.

    Ich ergänze: dass hier nichts optimiert werden kann, was es nicht in C++ auch kann.

    rischtich, allerdings kann die Java-VN noch zur laufzeit optimieren (und tut dies oft auch).
    🙂

    Das kann ich mit dem VC9 doch so ähnlich auch, da kompilier ich die Anwendung dann führ ich sie aus und anschließend kompilier ich sie erneut, nur dieses mal hat der Kompiler zusätzliche Informationen über das Laufzeitverhalten 🙂

    Die Kritik an den Java Referenzen ist doch unberechtigt, denn weder in C noch in Java kann ich sagen was foo( eineVariable ); tut, abgesehen davon, dass eineVariable nicht geändert wird. Aber wenn eineVariable in C ein Zeiger und in Java ein Objekt (bzw. eine Objektreferenz) ist, dann weiß ich erst nachdem ich nachgeschaut habe was eineVariable ist ob das refenzierte Objekt (möglicherweise) geändert wird.



  • C++-Programmierender schrieb:

    Das kann ich mit dem VC9 doch so ähnlich auch, da kompilier ich die Anwendung dann führ ich sie aus und anschließend kompilier ich sie erneut, nur dieses mal hat der Kompiler zusätzliche Informationen über das Laufzeitverhalten

    klar, das musste nur irgendwie automatisieren, also quelltext, compiler, linker und analysesystem irgendwie zusammenbringen, so dass der code in abhängigkeit von der umgebung immer wieder neu compiliert wird. 'closed world assumptions' würde prof84 jetzt buzzworden.
    🙂



  • asc schrieb:

    Wie du vielleicht gelesen hatte, habe ich explizit von Objekten gesprochen.

    Dann ist fuer dich also ein

    void strcpy(char* trg, char* src) {
      while(*trg++=*src++);
    }
    

    ebenfalls ein call by reference?

    Ne ne ne.
    Du kannst nicht einfach die Sachen definieren wie du willst. Java kennt nur call by value. Weil Objekte eben referenzen sind. Das ist relevant zu wissen. Natuerlich kannst du die objekte die referenziert werden aendern, aber eben nicht die referenzen selber.

    denk einfach mal an:

    public class InitPoint 
    { 
      static void clear( Point p ) 
      { 
        p=new Point( 0, 0 ); 
      } 
    
      public static void main( String[] args ) 
      { 
        Point q = new Point( 47, 11 );   // Coordinates (x=47,y=11) 
        clear( q ); 
        System.out.println( q.x );   // nicht 0 
      } 
    }
    

    Call by reference wuerde hier q auf (0,0) setzen. Aber es ist call by value, ergo passiert garnix. Das ist sehr relevant zu wissen, da du zB keine delete() funktion schreiben kannst die eine referenz auf null setzt.

    es ist also kein verstecktes detail sondern eine klare und einfache design entscheidung gewesen. alles wird by value uebergeben.



  • +fricky schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind

    Das kann meistens eben nicht zur Kompilierzeit festgestellt werden.

    +fricky schrieb:

    (bei dem tippfehler-beispiel)

    ...ich geb dir gleich Tippfehler...



  • maximAL schrieb:

    +fricky schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind

    Das kann meistens eben nicht zur Kompilierzeit festgestellt werden.

    +fricky schrieb:

    (bei dem tippfehler-beispiel)

    ...ich geb dir gleich Tippfehler...

    Du weißt doch es genügt, wenn der Kompiler Code erzeugt der in 99% der Fälle korrekt ist.



  • maximAL schrieb:

    +fricky schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind

    Das kann meistens eben nicht zur Kompilierzeit festgestellt werden.

    das ist sehr einfach festzustellen. du übergibst nämlich zwei mal das gleiche objekt. selbst meine Java-IDE (intellij-idea) hat bei deinem beispiel gemeckert, dass hier was nicht stimmen kann.
    🙂



  • void foo(int* lhs, int* rhs, int* val)
    {
      *lhs += *val;
      *rhs += *val;
    }
    

    OMG, mein Compiler kann diese Zeilen nicht optimieren. Parallelisierung ist nie einfach und die eigentliche Performance holt man nicht aus der Microoptimierung.

    adaptive optimization may take advantage

    Irgendwie stoert mich der Konjunktiv. Was ist denn nun wirklich?



  • knivil schrieb:

    void foo(int* lhs, int* rhs, int* val)
    {
      *lhs += *val;
      *rhs += *val;
    }
    

    OMG, mein Compiler kann diese Zeilen nicht optimieren.

    schreib mal 'restrict' vor die pointer (dein compiler muss aber C99 kennen, z.b. GCC). vielleicht tut er's ja dann.
    🙂



  • knivil schrieb:

    void foo(int* lhs, int* rhs, int* val)
    {
      *lhs += *val;
      *rhs += *val;
    }
    

    OMG, mein Compiler kann diese Zeilen nicht optimieren. Parallelisierung ist nie einfach und die eigentliche Performance holt man nicht aus der Microoptimierung.

    Das Problem ist, dass der Compiler quasi nichts parallelisieren kann. Das ist ein relevantes Problem.



  • schreib mal 'restrict' vor die pointer (dein compiler muss aber C99 kennen, z.b. GCC). vielleicht tut er's ja dann.

    bist du Reporter? 🤡



  • Das Problem ist, dass der Compiler quasi nichts parallelisieren kann. Das ist ein relevantes Problem.

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    C ist halt nah an der Maschine. Entweder abstrahiert man von der Maschine oder spezialisiert man fuer eine Maschine. C oder auch C++ tut beides nicht. Das ist kein Nachteil. Warum soll C++ alles koennen? Wenn man so etwas haben moechte, dann parallelisiert man selbst oder man nimmt sich z.B. eine funktionale Sprache und laesst sich parallelen Code generieren. In beiden Faellen muss man Gehirnschmalz investieren, zum einen parallelisiert man selbst oder muss halt die neue Sprache lernen. Und wenn jemand behaupt, dass z.B. Java schneller sein soll als C++, dann hat er vielleicht hier und da etwas weniger Gehirnschmalz investiert. Und dann auf die super tolle Jit-Blub verweisen, ich weiss nicht ...

    Ich koennte ja noch 'ne Geschichte zum Besten geben mit Agent Nero in Mission Iso-Image brennen. Installer: 500 MByte ... die modernen Alleskoenner. Ich will sie nicht.



  • knivil schrieb:

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    Jede Art von Parallelisierung.

    Das Problem ist nämlich, dass jedes Statement dass Pointer liest oder schreibt jedes andere Statement verändern kann. Egal welche Art der Parallelisierung - sogar in der Pipeline selber drinnen, ist mit Zeigern enorm problematisch.

    C ist halt nah an der Maschine. Entweder abstrahiert man von der Maschine oder spezialisiert man fuer eine Maschine. C oder auch C++ tut beides nicht. Das ist kein Nachteil. Warum soll C++ alles koennen? Wenn man so etwas haben moechte, dann parallelisiert man selbst oder man nimmt sich z.B. eine funktionale Sprache und laesst sich parallelen Code generieren.

    Es ist ein relevantes Problem dass C/C++ Code einfach in gewissen Situationen lahm ist. Da kannst du auch kein Gehirnschmalz oder sonstwas investieren - dieser Aspekt an C++ suckt einfach. Deshalb ist dringend restrict in C++ notwendig...

    Und wenn jemand behaupt, dass z.B. Java schneller sein soll als C++, dann hat er vielleicht hier und da etwas weniger Gehirnschmalz investiert. Und dann auf die super tolle Jit-Blub verweisen, ich weiss nicht ...

    Es ist aber so. In gewissen Situationen wird Java immer schneller sein als C++.



  • ist mit Zeigern enorm problematisch

    Vielleicht hilft es, Zeiger vorsichtig einzusetzen.

    In gewissen Situationen wird Java immer schneller sein als C++.

    Glauben ist gut, Kontrolle ist besser. Da ich wenig mit Java arbeite, kann ich nicht viel darueber sagen. Aber ich bin offen und schaue mir auch gern Beispiele an (sofern sie nicht allzu gross sind).



  • knivil schrieb:

    Glauben ist gut, Kontrolle ist besser. Da ich wenig mit Java arbeite, kann ich nicht viel darueber sagen. Aber ich bin offen und schaue mir auch gern Beispiele an (sofern sie nicht allzu gross sind).

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    PS:
    Zeiger vorsichtig einsetzen ist nicht. denn fast alles in C++ kommt irgendwie auf zeiger zurück. strings, arrays, jede datenstruktur. und das ist eben das problem.



  • Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂



  • +fricky schrieb:

    Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂

    👍

    Oder gleich std::copy<T>, welches sich auch noch spezialisieren lässt, und z.B. für bestimmte Datentypen einen speziellen Copy-Algo nutzen könnte (z.B. einen Blitter 😃 ).



  • +fricky schrieb:

    Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂

    Und wenn der =operator ueberladen worden ist?


Anmelden zum Antworten