Änderungen von Variablen in Variable speichern



  • Sizeof von hallo ergibt natürlich die Größe von int, und nicht 0. Wenn man die Adresse von hallo im Programm nimmt muss man auch (bei statischen Membern) Speicher für die Konstante zur Verfügung stellen, und dessen Größe ist logischerweise auch 4. Man könnte sogar mit const_cast-Gemeinheiten den Wert an dieser Stelle ändern.

    Aber darum gehts garnicht, das wichtige ist doch dass solche Konstanten in C++ (im Gegensatz zu C) vom Compiler als konstant angesehen und damit zur Compile-Zeit ersetzt werden können. Selbst wenn Du den Wert per const_cast zur Laufzeit änderst ist der Compiler berechtigt davon auszugehen dass Du das nicht tust.



  • Es ist halt ein Sprach-Element und kein Textersetzer-Element. Man man sollte immer Sprachelemente bevorzugen. Da der Compiler die Hoheit über den endgültigen Code hat.



  • LordJaxom schrieb:

    Sizeof von hallo ergibt natürlich die Größe von int, und nicht 0. Wenn man die Adresse von hallo im Programm nimmt muss man auch (bei statischen Membern) Speicher für die Konstante zur Verfügung stellen, und dessen Größe ist logischerweise auch 4. Man könnte sogar mit const_cast-Gemeinheiten den Wert an dieser Stelle ändern.

    hmmm? 😕
    jetzt bin ich ganz schön verwirrt. konstanten, deren wert man zur laufzeit ändern kann? wie passt denn das zusammen 😮
    so langsam komme ich zu dem schluss, dass #define hierfür doch besser geeignet ist.



  • Lies Lordjaxoms Beitrag noch mal genauer durch. Er hat nicht gesagt, das man einfach so zur Laufzeit einen const-Wert ändern kann. Sondern du mußt das schon mit speziellen Mitteln (const_cast) explizit zun. Im Übrigen: in C++ benutzt man eh enums oder man kapselt const-Variablen als private in Klassen. DIE kann man definitiv nicht ändern. Auch nicht mit nem const_cast. Wir reden hier die ganze Zeit über normale Variablen. Aber C++ hat mehr Sprachmittel, mit denen ich sowas ausschliessen kann.



  • Um es nochmal zu spezifizieren: Man kann mit const_cast viel gemeines tun, sogar statische Memberkonstanten ändern. Können im Sinne von es compiliert.

    Der Standard sagt aber dass das Entfernen von const und das darauffolgende Ändern eines Wertes nur dann definiert ist, wenn der Ursprungswert nicht konstant ist. Was undefiniert bedeutet, brauch ich Dir wohl nicht zu sagen 😉

    Das folgende Beispiel compiliert z.B. wunderbar, stürzt aber (MSVC++ 8.0, WinXP) mit einem Speicherzugriffsfehler ab, da der Ursprungswert konstant war.

    class ConstGehampel {
    public:
    	static const int guenelpf = 101;
    };
    
    int main(int argc, char* argv[])
    {
    	cout << sizeof(ConstGehampel::guenelpf) << endl; // Hat Größe
    	cout << &ConstGehampel::guenelpf << endl; // Hat Adresse
    
    	cout << ConstGehampel::guenelpf << endl;
    	const_cast<int&>(ConstGehampel::guenelpf) = 12; // BOOOOM
    	cout << ConstGehampel::guenelpf << endl;
    }
    


  • vista schrieb:

    ok, dass #define grundsätzlich fehlerträchtiger ist als etwas anderes kann ich nicht nachvollziehen, denn meistens handelt man sich fehlerquellen durch falsche anwendung ein und das kann auch mit anderen konstrukten passieren....

    Ja - aber mit kaum einer Technik ist es so leicht, Fehler zu machen, wie mit #define-s !
    Auf jeden Fall ist es viiiiiel schwerer, mit den obigen const-Konstrukten Fehler zu machen (fast nur mutwillig).

    Insgesamt teile ich genau die hier von Artchie, Konrad und CStoll formulierte Sorge bzgl. der Verwendung von #define-s.
    Mein "unschön" habe ich nur zurückgezogen, weil ich diese Probleme im vorliegenden Fall ("FELD0 (1<<0)") nicht akut sehe.

    Gruß,

    Simon2.



  • Wo ich auch C++ Sprachmittel den defines vorziehe:

    #define EINS 1
    #define ZWEI 2
    #define DREI 3
    

    Uuuuumständlich. Wenn ich sowas in C++ habe:

    enum {eins = 1, zwei, drei, zehn = 10, elf, zwoelf };
    

    Mit defines umständlicher, weil wenn ich mal eines "zwischenschieben" will, oder nur die Werte anders haben will, muß ich bei Makros schlechtestenfalls alle Makro-Werte ändern. enum zählt autom. weiter. Und ist noch typisiert.



  • LordJaxom schrieb:

    Der Standard sagt aber dass das Entfernen von const und das darauffolgende Ändern eines Wertes nur dann definiert ist, wenn der Ursprungswert nicht konstant ist.

    ah, ich glaube ich verstehe es jetzt 💡
    die eigenschaft 'konstanz' bedeutet in der C++-welt nicht das gleiche, wie in der physik, mathematik usw.
    'konstant' unter C++ ist so etwas wie ein temporärer schreibschutz, also etwas ist ursprünglich nicht konstant, dann mache ich es konstant und etwas später kann ich diese eigenschaft wieder entfernen. na, da muss man erst mal drauf kommen 🙂

    @Artchi:
    enums sind okay. die sind wirklich konstant. würde ich persönlich jedenfalls nehmen, um unter C++ konstanten zu definieren. enums sind ja eigentlich ein aufzählungstyp aber dass man sie zur laufzeit nicht ändern kann, ist ein guter grund, sie zur definition von konstanten zu 'missbrauchen'.
    🙂



  • vista schrieb:

    ah, ich glaube ich verstehe es jetzt 💡
    die eigenschaft 'konstanz' bedeutet in der C++-welt nicht das gleiche, wie in der physik, mathematik usw.
    'konstant' unter C++ ist so etwas wie ein temporärer schreibschutz, also etwas ist ursprünglich nicht konstant, dann mache ich es konstant und etwas später kann ich diese eigenschaft wieder entfernen.

    Genau. Es seidenn etwas ist ursprünglich konstant, dann ist das spätere Entfernen dieser Konstanz (in Verbindung mit einer Änderung des Datums) undefiniert.



  • vista schrieb:

    ...
    ah, ich glaube ich verstehe es jetzt 💡
    die eigenschaft 'konstanz' bedeutet in der C++-welt nicht das gleiche, wie in der physik, mathematik usw.
    'konstant' unter C++ ist so etwas wie ein temporärer schreibschutz, ...

    Vielleicht hilft es Dir, Dir klarzumachen, dass Du eine Variable (= ein Ding, das es nur zur Compilezeit gibt) konstant machst ! Letztlich liegt alles irgendwo im Speicher und kann natürlich dort überschrieben/geändert werden.
    Aber mit einem "const" teilst Du dem Compiler mit, dass Du den Wert hinter dieser Variable nicht ändern möchtest und er

    • Dir anzeigt, wo Du es doch versuchst und
    • bestimmte "Optimierungen" vornehmen kann (z.B. Verwendung durch Wert ersetzen, besondere Speicherbereiche für die Ablage wählen, ....).

    Gerade Zweiteres bringt Dich dann auf den Schmerzenspfad "Undefiniertes Verhalten", wenn Du mit Hacks diese Zusicherung brichst.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    vista schrieb:

    ...
    ah, ich glaube ich verstehe es jetzt 💡
    die eigenschaft 'konstanz' bedeutet in der C++-welt nicht das gleiche, wie in der physik, mathematik usw.
    'konstant' unter C++ ist so etwas wie ein temporärer schreibschutz, ...

    Vielleicht hilft es Dir, Dir klarzumachen, dass Du eine Variable (= ein Ding, das es nur zur Compilezeit gibt) konstant machst !

    sorry, simon, aber gerade das das hat micht so verwirrt. eine 'variable' ist ja per definition schon mal variabel, sprich: veränderlich. eine 'konstante' ist das genaue gegenteil davon. ihr wert ist und bleibt fest. man kann nicht das eine in das andere überführen.
    ich kann aber gut damit leben, dass unter C++ einiges offensichtlich anders ist und dass man mit logik dort nicht weit kommt 😉
    aber jetzt weiss ich es ja:
    ausgangszustand variabel -> const -> variabel == OK
    ausgangszustand const -> variabel == UNDEFINIERT
    ...und das 'const' in wirklichkeit nur ein 'pseudo-const' ist.

    Simon2 schrieb:

    Letztlich liegt alles irgendwo im Speicher und kann natürlich dort überschrieben/geändert werden.

    naja, das kommt auch wieder darauf an, in welcher art von speicher es sich befindet. konstanten gehören für gewöhnlich in einen bereich des speichers, der nicht veränderlich ist. beispiel:

    char *s = "hello, world";
    

    die stringkonstante "hello, world" wird im FLASH, oder auf einem PC im read-only bereich abgelegt, den das betriebssystem gegen schreibzugriffe schützt. verändern dieses speichers ist also ohne spezielle mittel nicht möglich d.h. eine gewisse konstanz kann man nicht abstreiten.



  • Du scheinst eine mathematische Variable mit einer Programmier-Variable zu verwechseln. Finde ich ein wenig gewagt. Dann würde es mir auch unlogisch erscheinen. Aber wir sind hier in einem Programmierforum und nicht Matheforum.

    Zitat aus http://de.wikipedia.org/wiki/Variable_(Programmierung):

    Variablen werden in der Programmierung dazu verwendet, den Quelltext lesbar zu halten

    Nichts anderes ist eine const-Variable in C++!

    Was anderes ist:
    http://de.wikipedia.org/wiki/Variable



  • vista schrieb:

    ...
    sorry, simon, aber gerade das das hat micht so verwirrt. eine 'variable' ist ja per definition schon mal variabel...

    😃 Naja, Du kannst natürlich weiterhin die Fachbegriffe unterschiedlicher Disziplinen mischen und Dich an den lustigen Farbenspielen der Logik erfreuen .... aber Dein Verstehen fördert das nicht. Und das ist absolut logisch ! 😃

    Ebensowenig wie eine "Transformation" in Musik, Biologie und Mathematik dasselbe meint, ist es mit "Variable" und "konstant".

    Bei der Programmierung bezeichnet man als "Variable" ein Element der Programmiersprache, das dazu dient, Daten zu halten.
    Desselben ist auch eine "const Variable" in der Programmierung NICHT das, was vielleicht ein Philosoph oder ein Agrarökonom darunter verstehen würde, sondern in C++ definiert als eine besondere Variable (s.o.) .. nämlich eine solche, die man nicht verändern darf/will/soll.

    vista schrieb:

    ...
    ausgangszustand variabel -> const -> variabel == OK
    ausgangszustand const -> variabel == UNDEFINIERT
    ...

    Das ist im C++-Standard so festgelegt ... in anderen Programmiersprachen kann das anders sein.

    vista schrieb:

    ...
    ...und das 'const' in wirklichkeit nur ein 'pseudo-const' ist.

    Was ist denn nach Deiner Definition "const" ? Wenn Du es wirklich mit (z.B. Natur-)Konstanten vergleichen wolltest, dürfte NIEMALS (auch nicht in späteren Softwareversionen) eine Konstante einen anderen Wert bekommen. ... ich glaube, Du stellst Dir hier selbst ein Bein und beschwerst Dich über die vermeintliche Holprigkeit des Weges.

    vista schrieb:

    ...

    Simon2 schrieb:

    Letztlich liegt alles irgendwo im Speicher und kann natürlich dort überschrieben/geändert werden.

    ...verändern dieses speichers ist also ohne spezielle mittel nicht möglich d.h. eine gewisse konstanz kann man nicht abstreiten.

    Ich habe nie behauptet, sie seien "ohne spezielle Mittel" veränderbar, sondern nur: Sie sind veränderbar (Anders als z.B. das Plancksche Wirkungsquantum).
    BTW: Was ist denn ein Debugger, Memorymonitor, .... andereres als "ein spezielles Mittel" ?

    Gruß,

    Simon2.



  • Artchi schrieb:

    Zitat aus http://de.wikipedia.org/wiki/Variable_(Programmierung):

    Variablen werden in der Programmierung dazu verwendet, den Quelltext lesbar zu halten

    da fehlt doch was 😉

    Variablen werden in der Programmierung dazu verwendet, den Quelltext lesbar zu halten sowie häufig gebrauchte Standardgrößen (Datentypen) von Speicherbereichen schnell und einfach nutzbar zu machen und zu ändern.



  • Simon2 schrieb:

    Was ist denn nach Deiner Definition "const" ? Wenn Du es wirklich mit (z.B. Natur-)Konstanten vergleichen wolltest, dürfte NIEMALS (auch nicht in späteren Softwareversionen) eine Konstante einen anderen Wert bekommen.

    nach meinem verständnis wäre ein 'echtes const', ein wert, den man beim programmieren und während der laufzeit nicht verändern kann, bis auf eine einzige ausnahme: man ändert bewusst die stelle im code, an der die konstante als solche definiert wird und macht sie damit zu einer variablen.

    Simon2 schrieb:

    ... ich glaube, Du stellst Dir hier selbst ein Bein und beschwerst Dich über die vermeintliche Holprigkeit des Weges.

    nein, ich beschwere mich ja nicht. ich habe jetzt verstanden wie der hase läuft und muss das so hinnehmen. ob ich es gut oder schlecht finde, ist ein anderes thema 😉



  • vista schrieb:

    ...nach meinem verständnis wäre ein 'echtes const', ein wert, den man beim programmieren und während der laufzeit nicht verändern kann, bis auf eine einzige ausnahme: man ändert bewusst die stelle im code, an der die konstante als solche definiert wird und macht sie damit zu einer variablen....

    Ich glaube, Du meinst nicht "Wert", denn einen "Wert" kannst Du sowieso nicht ändern, sondern nur durch einen anderen ersetzen: Eine 3 bleibt immer eine 3 ...
    Du meinst "ein Ding, dem man einen Wert zuweisen kann"
    .... und eine "Konstante" ist dann "ein Ding, dem man nur an einer Stelle einmalig einen Wert zuweisen kann".
    Und genau das hast Du doch:

    int const unveraenderbares_ding = 3;
    

    Alles, was Dir hier erzählt wurde über "kann man doch ändern", bezieht sich auf "Hacks", die man nicht mit der Definition einer Programmiersprache verhindern kann (außer eben: "Tut das nicht, sonst garantiere ich für nichts mehr" = "undefiniertes Verhalten").

    Wodurch Konfusion entsteht ist, dass man dieses "Ding" (Was halt "Variable" genannt wird .... kannst aber auch "Bezeichner" sagen) ja irgendwie auch mal verwenden will in seinem Programm:

    void f(int& x);   // Diese Funktion kann "dinger" nutzen und bezeichet sie als x
    

    Aber hoppla: So kann f ja auch versuchen, dem übergebenen "Ding" einen anderen Wert zuzuweisen.... das kann gut gehen, wenn sich dahinter eine Nichtkonstante verbirgt, aber was, enn wir das mit "ding" aufrufen ?
    Hier kann man sich auf die Zusicherung des Programmierers ("Mache ich gaaaaaaanz bestimmt nicht !") verlassen .... aber das war den C++-Designern zu unsicher, also haben sie das verboten unds gefordert: Wenn ein f-Programmierer Konstanten empfangen können will, muß er das entsprechend kennzeichnen .... und wird dann vom Compiler darauf festgenagelt.
    und wählten die Syntax:

    void f(int const& x);
    

    Damit kann der Compiler prüfen, ob der Programmierer nicht doch aus Versehen am übergebenen Ding rumändert.
    ... und plötzlich haben wir eine zweite Art von "Konstante": Nämlich einen Bezeichner, der mal diesem, mal jenem "Ding" zugeordnet wird, über den aber NIE der Wert des zugewiesee Dings geändert werden darf.
    Auch das nennt man "konst-Variable" ....

    void f(int const& x);
    int main() { 
        int const unveraenderbares_ding = 3;
        int ding = 5;
    
        f(unveraenderbares_ding); // jetzt zeigt x auf unveraenderbares_ding
        f(ding); // jetzt zeigt x auf ding
        // Hoppla !!! Obwohl x doch "konstant" ist, zeigt es zur Laufzeit auf verschiedenes !!
    ...
    

    (der "const_cast-Hack" bezieht sich lediglich darauf, dass jemand ihn auf x anwendet ... nur dann kann er (definiert) funktionieren)

    "Konstantheit" ist in der Realität immer (nicht nur in der Programmierung) eine Frage des Gültigkeitsbereichs
    ... und innerhalb des "Laufzeitbereichs von main()" ist unveraenderbares_ding konstant.
    ... und innerhalb des "Laufzeitbereichs von f()" ist x konstant.
    Verlässt man diesen Bereich, werden sie evtl. doch anderen Werten zugeordnet...
    ich denke immer noch, dass Du nicht durch zu hohe, sondern nur durch mangelnde Differenzierung Deine Bauchschmerzen bekommen hast. 😉

    Gruß,

    Simon2.



  • hallo simon,
    danke, dass du dir solche mühe mit mir machst 😉
    dein beispiel ist klar und bestätigt auch mein verständnis von 'const' unter C++.
    du hättest natürlich auch den wert an f() 'by value' und nicht als referenz übergeben können, dann hättest du kein 'const' gebraucht um sicher zu stellen, dass der ursprungswert nicht verändert werden kann.
    aber mal angenommen wir hätten den umgekehrten fall:

    void f (int &x)
    {
     ...
    }
    
    int main()
    {
        const int a = 1;
        f ((int&)a);
    }
    

    die typänderung von 'const int' in 'int&' erzeugt undefiniertes verhalten, das ist mir klar - aber - wieso compiliert das? müsste ein C++ compiler sich hier nicht beschweren?
    wäre in dem fall ein #define nicht besser, weil man es nicht in eine int-referenz casten kann und der compiler sofort mit einem fehler abbrechen würde, wenn man versucht aus der vermeintlichen 'konstanten' eine variable zu machen?
    🙂



  • vista schrieb:

    die typänderung von 'const int' in 'int&' erzeugt undefiniertes verhalten, das ist mir klar - aber - wieso compiliert das? müsste ein C++ compiler sich hier nicht beschweren?

    Würde er doch - ohne den Cast.
    Ein Cast allerdings sagt doch im Grunde dem Compiler (und das gilt genauso in Plain C) "ich weiss es besser als Du, also mach!". Wenn Du dort absichtlich (und so ein Cast auf eine Referenz ist imho nicht unbedingt so alltäglich dass man das aus Unwissenheit heruntertippt) das const weg-castest bist Du doch selbst schuld 😉

    Darüberhinaus würde sich ein großes Problem ergeben, wenn die Möglichkeit const weg-zu-casten nicht gegeben wäre, denn stellen wir uns ein (leider immernoch alltägliches) Beispiel der Anbindung von C und C++ vor:

    /* Ältere aber bewährte C-API */
    void draw_text(xy_image* img, xy_font* font, int x, int y, char* text);
    
    /* Ordentliches C++-Programm */
    std::string title = "My Hello World Picture";
    xy_image* img = xy_create_image(800, 600, CLR_ARGB);
    xy_font = xy_create_font("Times New Roman", 12.f);
    draw_text(img, font, 100, 100, title.c_str()); // Oops, die alte, aber bewährte C-API ist nicht const-correct
    // Aus irgendeinem Grund wissen wir aber 100%ig dass draw_text den Text nur liest und nicht ändert:
    draw_text(img, font, 100, 100, const_cast<char*>(title.c_str())); // oder, C-style
    draw_text(img, font, 100, 100, (char*) title.c_str());
    

    Wenn man sowas dann schön wrappt, hat man genau einen "bösen" Cast im Programm und kann ansonsten über den Wrapper schön mit konstanten Strings oder std::strings hantieren 😉



  • vista schrieb:

    ...wieso compiliert das? ...

    Weil das einer der besagten "Hacks" ist. Ein "C-Style-Cast", wie Du ihn hier verwendest ist noch "brutaler" als die C++-Casts (z.B. const_cast) .... damit sagst Du: "Ich selbst übernehme die volle Verantwortung für das hier - Mach das !" .... was soll der Compiler denn dazu schon noch sagen ?
    Du vergleichst hier den Teufel mit Beelzebub: casts sind "einigermaßen böse", #defines sind "sehr böse" ... 😉
    Verzichte auf Beides und Du wirst ein glücklicherer Programmierer sein.

    Gruß,

    Simon2.



  • LordJaxom schrieb:

    Wenn man sowas dann schön wrappt, hat man genau einen "bösen" Cast im Programm und kann ansonsten über den Wrapper schön mit konstanten Strings oder std::strings hantieren 😉

    aha 💡
    ich nähere mich so langsam der erleuchtung 😉
    dann ist es also so, dass das willkürliche setzen und entfernen des 'const' attributes allein aus dem grund existiert, damit man von C++ aus alte C-funktionen aufrufen kann?
    ein kleiner zweifel bleibt aber noch: du sagtest dass wenn das ursprungsobjekt 'const' ist und man das const entfernt, undefiniertes verhalten provoziert wird.
    in deinem beispiel (verwendung von alten C-funktionen) gehst du stillschweigend davon aus, dass das entfernen von 'const' zumindest soweit funktioniert, als das die richtige adresse übergeben wird.
    kann man das?
    nach meinen verständnis bedeutet undefiniertes verhalten, dass das ergebnis einer solchen aktion absolut unvorhersehbar ist. oder nehme ich da wieder etwas zu wörtlich?

    Simon2 schrieb:

    Du vergleichst hier den Teufel mit Beelzebub: casts sind "einigermaßen böse", #defines sind "sehr böse" ... 😉
    Verzichte auf Beides und Du wirst ein glücklicherer Programmierer sein.

    wie du an LordJaxoms beispiel sehen kannst, ist ein cast manchmal nötig.
    oder kennst du einen besseren weg, wie man die C-funktion aufrufen könnte?


Anmelden zum Antworten