Konstaten wirklich invariabel?



  • @SeppJ sagte in Konstaten wirklich invariabel?:

    Das stimmt aber auch nur, solange sie physisch überhaupt existieren. Konstanten sind schließlich super Kandidaten für totale Wegoptimierung. Daher ist das auch undefiniertes Verhalten, eine Konstante über Hacks zu ändern, denn man kann das Programmverhalten dann in Angesicht von Optimierungen nicht mehr vorhersehen:

    	const int c = 3;
    	const int *cp = &c;
    	int * p = const_cast<int*>(cp);
    	*p = 4;
    	for (int i = 0; i < c; ++i)
    		cout << i;
    

    Da wurde vielleicht die Schleife 3x abgerollt. Oder das ganze Programm zu puts("012"); optimiert. Oder nichts davon. Oder ganz was anderes.

    Wenn du mal noch eine Ebene weiter rausgehst, wirst du feststellen, das die Konstante trotzdem irgendwie abgespeichert wurde - also physisch existieren muss - wenn sie irgendwie benutzt werden soll. Also z.B. ist die "3" gespeichert indem dreimal der Code untereinander kopiert ist, grad kurz in Godbolt getestet:

            xor     esi, esi
            mov     edi, OFFSET FLAT:_ZSt4cout
            call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
            mov     esi, 1
            mov     edi, OFFSET FLAT:_ZSt4cout
            call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
            mov     esi, 2
            mov     edi, OFFSET FLAT:_ZSt4cout
            call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
    
    

    Und auch das ist nun lange nicht konstant, denn weitere Kopien einfügen/löschen ist hier sogar recht trivial. Das wird praktisch natürlich komplexer als in dem Beispiel, was aber an der theoretischen Aussage nichts ändert.



  • @Jockelx sagte in Konstaten wirklich invariabel?:

    Ich bin mir ziemlich sicher, dass das nicht stimmt. Das Beispiel was du wahrscheinlich im Kopf hast, ist das hinzu casten von const, um eine gleichnamige const Funktion nutzen zu können und Codeverdopplung zu vermeiden.

    Nein, es geht um das WEGcasten von const. Hier: https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func



  • @wob Mmmh?
    Die non-const Funktion ruft die const Funktion auf. Der non-const wird also ein const hinzugefügt.
    (das ist übrigens das Beispiel was ich meinte)


  • Mod

    @TGGC sagte in Konstaten wirklich invariabel?:

    [...]

    Das ist dann aber eine ziemlich nutzlose Aussage.



  • @SeppJ Könnte man dann bald mit "ja, Computer sind programmierbar" zusammenfassen 😉



  • @Jockelx sagte in Konstaten wirklich invariabel?:

    @wob Mmmh?
    Die non-const Funktion ruft die const Funktion auf. Der non-const wird also ein const hinzugefügt.
    (das ist übrigens das Beispiel was ich meinte)

    Hm. Vielleicht verstehe ich dich nicht richtig.

       Z& Z(size_t index)
       {
          // One line. One ugly, ugly line - but just one line!
          return const_cast<Z&>( static_cast<const X&>(*this).Z(index) );
       }
    

    Hier wird doch eindeutig mit const_cast das const WEGgecastet, damit man die const-Funktion benutzen kann, um ein non-const-Ergebnis zu liefern.

    Edit: ah, ich glaube, ich verstehe, was du meinst. Du beziehst dich auf den zweiten Cast dort, der jetzt auch als durch std::as_const ersetzt werden könnte? Es ging mir um das "Man kann constness weg casten und dann etwas zuweisen. " worauf du "Ich bin mir ziemlich sicher, dass das nicht stimmt." sagtest. Ich sage: doch, man kann es wegcasten und dann was zuweisen (gut, nachdem in der Funktion das const erst hinzugecastet wurde, aber darauf bezog ich mich nicht)



  • @hustbaer sagte in Konstaten wirklich invariabel?:

    @SeppJ Könnte man dann bald mit "ja, Computer sind programmierbar" zusammenfassen 😉

    Richtig und daher existieren Konstanten eben nur auf einem gewissen Level der Abstraktion.

    @SeppJ sagte in Konstaten wirklich invariabel?:

    @TGGC sagte in Konstaten wirklich invariabel?:

    [...]

    Das ist dann aber eine ziemlich nutzlose Aussage.

    Kommt drauf an, warum man die Frage stellt. Die Antwort gibt ja nun mal die Realität wieder.



  • @wob
    Ja, okay, technisch hast du Recht. Ich habe mir das jetzt nicht genau angeschaut, weil ich den Tipp noch ganz gut im Gedächnis hatte und er x mal darauf hingewiesen hat, dass er immer nur mit non-const Dingen const Dinge macht.
    Und die Sichtweise hatte ich jetzt auch nur im Blick: mache etwas const und rufe damit const Funktionen auf. Niemals anders herum!
    Heisst: Füge const hinzu. Aber ja, technisch hast du Recht; das hinzugefügte const muss am Ende natürlich wieder entfernt werden.



  • @Jockelx sagte in Konstaten wirklich invariabel?:

    h den Tipp noch ganz gut im Gedächnis hatte und er x mal darauf hingewiesen hat, dass er immer nur mit non-const Dingen const Dinge macht.

    Ah das hatte ich dann falsch im Gedächtnis.
    Ich hab das noch nie gebraucht, weil ich noch nie ne Funktion in const und non const hatte die das gleiche macht. denk, vllt doch aber das waren one-liner.

    EDIT: Könnte das mal gemacht haben ohne drüber nachzudenken.
    Dass ich das Buch gelesen habe ist mindestens 8 Jahre her.



  • @TGGC
    Doch, Konstanten* sind invariabel. Denn Konstanten sind eine Abstraktion. Dass eine konkrete Umsetzung dieser Abstraktion dann oftmals nicht perfekt ist und trotzdem irgendwie eine Änderung zulässt, ist dann wieder was anderes.

    Und, wenn ich dich diesbezüglich richtig verstanden habe: Wie das Neuübersetzen eines (geänderten) Programms das Ändern einer Konstante darstellen soll, das müsstest du mir auch erstmal erklären. Nur weil ich etwas zerstören und dann in anderer Form neu erschaffen kann heisst das nicht dass ich es ändern kann. Weil das neue Ding nicht mehr die selbe Identität hat wie das alte.

    *: "Echte" Konstanten, so wie C++ static const int & Co.



  • Ob das was Anderes ist oder nicht, kommt ganz drauf an um was es geht.

    Ich sprach auch gar nicht davon, das Neuübersetzen eine Konstante ändert, sondern das es den Code ändert.



  • Ich finde die philosophisch anmutende Diskussion, ob Konstanten konstant oder nur abstrakt konstant sind, nicht sonderlich hilfreich.

    Der TE hat Probleme bei der sematischen Interpretation von i von i + 1. Er ist also noch etwas unerfahren in C++.

    Und nun sieht er, wie sich ein Forum darüber streitet, ob const int konstant ist oder nicht. Warum sollte er da nicht denken: "Wenn das Forum nicht weis, ob const int konstant ist oder nicht, warum sollte ich dann überhaupt const nutzen?"

    Und das würde dazu führen, dass der TE ein meines Erachtens wichtiges Hilfsmittel nicht nutzt. Ein Hilfsmittel welches ausdrückt: Lieber Entwickler es ist von mir nicht angedacht die Variable/Parameter zu ändern. Solltest du nach Seiteneffekten wg. Parametern suchen, so habe ich den Parameter nicht verändert...

    PS:
    Ironischerweise hat in der Embedded Welt const irgentwie seine ursprüngliche Bedeutung verloren. Bei einigen MCU's landen static const im FLASH ROM. Bei gesetzten Lock Bits und vergossenem Programmierport kann man danach gar nichts mehr ändern.

    https://community.st.com/s/question/0D50X00009XkY1qSAF/store-constant-variables-in-flash
    https://stackoverflow.com/questions/54532302/static-const-vs-const-declaration-performance-difference-on-uc

    Das Ganze ist offenbar so verbreitet, das bei einigen Entwickler der Gedanke "const = ROM" aufkam und dadurch vermutlich Mempory Specifier wie PROGMEM eingeführt wurden.

    https://www.nongnu.org/avr-libc/user-manual/pgmspace.html


  • Mod

    @Quiche-Lorraine sagte in Konstaten wirklich invariabel?:

    PS:
    Ironischerweise hat in der Embedded Welt const irgentwie seine ursprüngliche Bedeutung verloren. Bei einigen MCU's landen static const im FLASH ROM. Bei gesetzten Lock Bits und vergossenem Programmierport kann man danach gar nichts mehr ändern.

    War das überhaupt jemals seine Bedeutung? Nach allem was ich weiß (und das ich auch gerade noch einmal bestätigt habe), hat das Konzept von const-Variablen seinen Ursprung in High-Level Programmiersprachen (tatsächlich wird sogar oft auf C++ als ersten Vertreter verwiesen). Das heißt, es gab niemals eine low-level Beziehung zu irgendeiner Hardwarespezialität (wie es z.B. bei register oder volatile ist), sondern es war stets nur auf Hochspachenebene als Hilfsmittel für den Programmierer gedacht, damit die invarianten der Programmlogik nicht versehentlich verletzt werden können.

    Das kann man historisch auch daran sehen, dass "echte" Konstanten in historischem C89 durch Makros erreicht wurden, nicht etwa durch const int, welches nicht als Compilezeitkonstante galt. Wenn irgendetwas wirklich eine Konstante für den ROM (oder auch eine geschützte Speicherseite für Programmcode) war, dann hätte man es als Literal oder Makro in den Quellcode getan und gehofft, dass der Compiler den Wert dann auch fest in das Maschinenprogramm einfügt. Was er dann auch getan hat. Bei einem const int hätte hingegen durchaus eine gute Chance bestanden, dass dieser bei unoptimierten Code wirklich irgendwo auf dem Stack liegt.



  • @SeppJ sagte in Konstaten wirklich invariabel?:

    es war stets nur auf Hochspachenebene als Hilfsmittel für den Programmierer gedacht

    Viel mehr wollte ich auch gar nicht beitragen, vor allem da mir die Intention komplett unklar ist.



  • Nein, Konstanten sind nicht invariabel.

    In C++ sind die im Gegensatz zu C invariabel. Ein Lesezugriff wird immer zur Compile-Zeit "geerdet".
    Du kannst zwar das const per const_cast wegcasten und der Compiler darf theoretisch die Variable dann ins Binary nehmen und dort auch schreiben, aber er darf auch den Schreibzugriff wegoptimieren. MSVC und g++ tun das entsprechend, clang tut das nicht.


  • Mod

    Wenn du glaubst, hier gäbe es irgendwelche Unterschiede zwischen C und C++, dann ist schon deine Eingangsannahme komplett falsch.



  • @SeppJ sagte in Konstaten wirklich invariabel?:

    Wenn du glaubst, hier gäbe es irgendwelche Unterschiede zwischen C und C++, dann ist schon deine Eingangsannahme komplett falsch.

    Doch, hier gibt es einen Unterschied zwischen C und C++. Weil in C const-Werte nicht immer compile-time-konstant sind nutzt man ja #define's für Konstanten. In C++ ist das nicht mehr nötig.



  • Wo ist da die compile-time-konstante?

    void func(const int x)
    {
        std::cout << x;
    }
    
    int main()
    {
        int y;
        if(std::cin >> y)
        {
            func(y);        
        }
    }
    

  • Mod

    @Flodul sagte in Konstaten wirklich invariabel?:

    @SeppJ sagte in Konstaten wirklich invariabel?:

    Wenn du glaubst, hier gäbe es irgendwelche Unterschiede zwischen C und C++, dann ist schon deine Eingangsannahme komplett falsch.

    Doch, hier gibt es einen Unterschied zwischen C und C++. Weil in C const-Werte nicht immer compile-time-konstant sind nutzt man ja #define's für Konstanten. In C++ ist das nicht mehr nötig.

    Das ist ein rein syntaktischer Unterschied.



  • @LeMace sagte in Konstaten wirklich invariabel?:

    Wo ist da die compile-time-konstante?

    void func(const int x)
    {
        std::cout << x;
    }
    
    int main()
    {
        int y;
        if(std::cin >> y)
        {
            func(y);        
        }
    }
    

    Nirgends. Und ...?


Anmelden zum Antworten