Änderungen von Variablen in Variable speichern



  • vista schrieb:

    du hast es absichtlich falsch gemacht. damit kannst du niemanden überzeugen.

    Bei der Verwendung von PI ist mir eine exakt berechnete Version auf jeden Fall lieber als ein fest vorgegebener Wert (klar, für die meisten Anwendungen reicht sogar 3.14, aber sag das mal einem Puristen :D). Und ansonsten zeigen die Beispiele recht deutlich die Probleme des Präprozessors - #define ist eine dumpfe Textersetzung und wenn dabei Fehler auftreten, kannst du die nur schwer lokalisieren.
    In C war #define womöglich noch verwendbar, aber in C++ ist es in den meisten Fällen unnötig (da gibt es Möglichkeiten mit vergleichbarer Anwendbarkeit, aber ohne die Schwächen des Präprozessors).



  • vista schrieb:

    Konrad Rudolph schrieb:

    #define pi (std::atan(1.0) * 4.0)
    #define drei 2 + 1
    

    du hast es absichtlich falsch gemacht.

    Natürlich. Ich sagte ja auch, es sei fehleranfällig. Was glaubst Du, wie häufig diese Klammern vergessen werden!

    damit kannst du niemanden überzeugen.

    Jedem das seine. Aber in großen Teamprojekten ist man über jede eliminierte potentielle Fehlerquelle froh.

    Natürlich kann man auch mit #defines's fehlerfreien Code schreiben, das habe ich nicht bestritten. Aber es ist definitiv schwerer, als wenn man es sein lässt.

    #define pi 3.1415926536
    

    Ich bevorzuge die Definition über den Arkustangens.



  • 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.
    ..und dass #define immer eine stumpfe textersetzung macht ist auch nicht ganz richtig. etwas rechnen kann es ja auch.
    aber da ich von C++ null plan habe (ich programmiere meistens C), schenke ich euch mein blindes vertrauen und glaube euch, dass es in C++ andere möglichkeiten gibt, die besser ins konzept der sprache passen und die man als C++ progger deshalb #define vorziehen sollte.
    🙂



  • vista schrieb:

    ..und dass #define immer eine stumpfe textersetzung macht ist auch nicht ganz richtig. etwas rechnen kann es ja auch.

    Echt? Das beste, was der Präprozessor "rechnen" kann, sind die Operatoren # und ##. Bei einem #define drei (1+2) wird jedes Vorkommen von 'drei' textuell ersetzt, ohne daß der Präprozessor sind den Inhalt der Ersetzung ansieht - der Rest ist dann Sache des Compilers (der die Berechnung von (1+2) rausoptimieren kann).



  • CStoll schrieb:

    vista schrieb:

    ..und dass #define immer eine stumpfe textersetzung macht ist auch nicht ganz richtig. etwas rechnen kann es ja auch.

    Echt? Das beste, was der Präprozessor "rechnen" kann, sind die Operatoren # und ##. Bei einem #define drei (1+2) wird jedes Vorkommen von 'drei' textuell ersetzt, ohne daß der Präprozessor sind den Inhalt der Ersetzung ansieht - der Rest ist dann Sache des Compilers (der die Berechnung von (1+2) rausoptimieren kann).

    ich kann mich jetzt täuschen, aber als ich mir mal c-code nach dem preprocessor-durchlauf angeschaut habe (war' s jetzt beim codewarrior?)
    da wurde so etwas:

    #define drei (1+2)
    ...
    int x = drei;
    

    das:

    int x = 3;
    

    mag aber sein, das in der regel die präprozessoren nicht so schlau sind...
    🙂



  • Der Compiler macht eine 3 draus, wenn er das sieht. Aber nicht der Präprozessor. Und ja, du hast von C++ keinen Plan, sonst würdest du das nicht so in deinem jugendlichen Leichtsinn sagen, das Makros nicht so übel sind. Denn du mußt dir einem bewusst werden:

    static const int hallo = 2;
    

    Das Ding verbraucht KEINEN Speicher. (außer der Compiler ist so dämlich, aber dann würde ich den nicht weiter benutzen) Ich habe also nicht nur wie Makros keinen Speicherverbrauch, sondern auch noch ein Sprach-Element in Gebraucht. Ich kann das Hallo sogar in einen Namespace legen. Das geht alles nicht mit Makros. Es gibt KEINEN Grund dafür, wenn man C++ programmiert.



  • Artchi schrieb:

    static const int hallo = 2;
    

    Das Ding verbraucht KEINEN Speicher.

    demnach müsste ein 'sizeof(hallo)' 0 ergeben.
    ist es so?
    wäre jedenfalls unlogisch wenn nicht...
    🙂



  • Stimmt. *mir selbst in den arsch tritt*



  • 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


Anmelden zum Antworten