Änderungen von Variablen in Variable speichern



  • 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?



  • vista schrieb:

    ...
    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?

    Ja - ohne cast. 😉

    Ich weiß, dass man im Zusammenhang mit APIs bisweilen nicht drumherumkommt (deswegen schrieb ich auch "einigermaßen"), aber es ist auch dann oft das schlechte Design der API dafür verantwortlich (ggf. geht's sprachbedingt nicht besser - ändert aber nichts daran).
    Niemand hätte den Designer von

    /* Ältere aber bewährte C-API */
    void draw_text(xy_image* img, xy_font* font, int x, int y, char* text);
    

    daran gehindert, den letzten Parameter als char const* zu deklarieren - wenn er denn wirklich beabsichtigt, text nicht zu ändern.

    Allerdings haben ältere C-(NICHT C++ !)-Compiler bisweilen ein etwas seltsames Versändnis von const und monieren IMO unbedenkliche Zuweisungen und andere wieder nicht, wie z.B.:

    char *nonconst_p = "Simon2"; // => keine Fehlermeldung
          // seltsam: Der Compiler weiß, dass der Literal "Simon2" nicht mehr geändert werden darf;
          // trotzdem ist die Zuweisung zu einer nonconst-Variable erlaubt. (aus Tradition auch im C++-Standard)
       char const *const_p = nonconst; // alter C-Compiler: Warning: incompatible types
          // Wenn ich zusichere, via const_p den Speicher NICHT zu verändern, obwohl
          // nonconst das zuließe: Was stört ihn das ?
          // Besonders krude: In diesem Fall verweist nonconst letztlich auf einen unveränderbaren Bereich,
          // dem ein const-Ponter sowieso besser anstände.
    

    So gesehen habe ich ein gewisses Verständnis für diese Probleme ...

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Niemand hätte den Designer von

    /* Ältere aber bewährte C-API */
    void draw_text(xy_image* img, xy_font* font, int x, int y, char* text);
    

    daran gehindert, den letzten Parameter als char const* zu deklarieren - wenn er denn wirklich beabsichtigt, text nicht zu ändern.

    Von hätte hamwer nix 🙂

    Im Ernst, ich habe dieses Beispiel gewählt weil ich genau dieses Problem neulich hatte. Aufgabe war, Hintergrundbilder für eine DVD zu erstellen (Text auf Vorlage rendern, um genau zu sein), und dafür eine Bibliothek zu verwenden, die möglichst verbreitet oder auf einer Standardinstallation sogar schon vorhanden war.

    Die Wahl fiel auf GD, weil das die Standardlösung für Bilderzeugung in Perl ist und Perl samt GD::Graph zur Standardausstattung der Distribution gehörte. Als ordentlicher C++ler habe ich natürlich GD gewrappt und intern mit std::strings hantiert. Und die Textfunktionen von GD nehmen alle ein char*. Ich habe den Maintainer seinerzeit angesprochen, und er gab mir Recht, dass GD const-correcter sein könnte, jedoch habe er momentan nicht die Zeit sich darum zu kümmern (davon ab ist die letzte Release von GD schon einige Zeit her, das Ding gilt soweit als stable). Dabei hat er mir übrigens auch garantiert dass die Texte tatsächlich nur gelesen werden.

    @vista:
    Ich kenne den exakten Passus im Standard nicht, aber ich habe es immer so gehandhabt, dass das undefinierte Verhalten durch "wegcasten und schreiben" hervorgerufen wird, nicht durch "wegcasten aber trotzdem nur lesen". Hat bisher auch immer geklappt 🤡



  • LordJaxom schrieb:

    Simon2 schrieb:

    Niemand hätte den Designer von

    /* Ältere aber bewährte C-API */
    void draw_text(xy_image* img, xy_font* font, int x, int y, char* text);
    

    daran gehindert, den letzten Parameter als char const* zu deklarieren - wenn er denn wirklich beabsichtigt, text nicht zu ändern.

    Von hätte hamwer nix :)...

    Ich weiß - deswegen gibt's ja auch die casts (schön, dass man in C++ ein Mittel hat, mit dem man auf die Designfehler anderer reagieren kann)... und deswegen braucht man die auch bisweilen. Trotzdem sind sie IMO ein "böseres" Sprachmittel als for, const, class, ....

    Gruß,

    Simon2.


Anmelden zum Antworten