Cast von MAKRO nach int



  • knivil schrieb:

    Noch ne Gegenfrage: Von welchem Typ sind 234, 1, 6 oder 13? Sind sie natuerliche Zahlen, ganze, gebrochene, reele oder gar komplexe? Sie sind alles! Deswegen ist die Frage nach dem Typ von Zahlen eine schlecht gestellte Frage. Variablen haben Typen, Zahlen im allgemeinen nicht.

    Falsch, falsch, falsch!

    void function(int value);
    void function(short value);
    void function(unsigned int value);
    
    ...
    
    int main()
    {
        function(25);
    }
    

    Na, welche Funktion wird hier wohl aufgerufen? 😕
    Antwort: Die mit int. 😮
    Weil eine Zahl, die keinem Typ zugewiesen ist, per default ein int ist und nicht "alles". 🕶
    Booyashaka!



  • I know it better schrieb:

    [...]Weil eine Zahl, die keinem Typ zugewiesen ist, per default ein int ist und nicht "alles".[...]

    Das stimmt auch nicht.
    Was wird z.B. hierbei aufgerufen:

    function(42.0);
    

    😕
    Dabei hat die Zahl auch keinen Typen "zugewiesen", und trotzdem ist es kein int.

    Edit: komische Schreibfehler und eigene Blödheit



  • Tachyon schrieb:

    Das hat die Zahl auch keinen Typen "zugewiesen", und trotzdem ist es kein int.

    Ich bin mir gerade nicht sicher ob 42.0 double oder float, glaube aber ersteres ist.



  • Tachyon schrieb:

    I know it better schrieb:

    [...]Weil eine Zahl, die keinem Typ zugewiesen ist, per default ein int ist und nicht "alles".[...]

    Das stimmt auch nicht.

    [...]Weil eine literale Zahl, die ohne Angabe eines Dezimalpunkts notiert ist, ohne Typpostfix automatisch ein int ist.

    (Der Passus "keinem Typ zugewiesen" ist so auch mißverständlich. Durch die Zuweisung an eine Variable vom Typ != int ändert sich nämlich der Typ des Literals nicht)



  • lord.hong schrieb:

    Wo liegt dann genau der Unterschied zwischen diesen zwei Zeilen:

    #define NUMBER 4711
    const int NUMBER = 4711;
    

    Soll das wirkilich identisch sein?

    Ein möglicher Unterschied ist folgendes (vorsicht, das Makro-Gefrickel wird nicht für zu Hause empfohlen ;))

    #define NUMBER 4711
    
    double foo4711();
    double foo4712();
    
    void bar()
    {
      int i = NUMBER; //okay, das ginge auch mit const int NUMBER...
      float f = 0.34##NUMBER##f; //0.344711f !!
      double d = foo##NUMBER##(); //Aufruf von foo4711() 
    }
    

    Soll heißen: Makros sind wirklich nur reine Textersetzung die man sogar als Teilstrings von Variablennamen benutzen kann. Der Compiler sieht nichts davon, deshalb kannst du bei Makros auf Typsicherheit und sinnvolle Fehlermeldungen nicht zählen - einer der Hauptgründe weshalb sie soweit möglich gemieden werden.



  • LordJaxom schrieb:

    Beim #define sieht der Compiler von NUMBER nichts mehr. Der Compiler sieht, überall wo vor dem Präprozessorlauf NUMBER stand, nun ein Integerliteral mit dem Wert 4711.

    Beim const int sieht der Compiler ein Symbol NUMBER, welches er (wegen dem const) bei jedem Auftauchen durch seinen Wert 4711 ersetzen darf (aber IMO nicht muss). Ein Unterschied ist z.B., dass man hier mit &NUMBER eine Adresse nehmen kann.

    Danke, dass war mein Problem. Der Compiler sieht nur noch 4711, was er als int interpretiert - was in meinem Beispiel auch richtig ist.

    Mit einem Postfix f

    #define NUMBER 4711f
    

    könnte ich den Typ float erzwingen oder einen implizieten cast vornehmen

    #define NUMBER 4711
    void doSomething( float fNumber);
    doSomething( NUMBER );
    doSomething( 4711 );
    

    Nun ist mir klar, wie der Compiler den Typ herausfindet.



  • pumuckl schrieb:

    Soll heißen: Makros sind wirklich nur reine Textersetzung die man sogar als Teilstrings von Variablennamen benutzen kann. Der Compiler sieht nichts davon, deshalb kannst du bei Makros auf Typsicherheit und sinnvolle Fehlermeldungen nicht zählen - einer der Hauptgründe weshalb sie soweit möglich gemieden werden.

    Stimmt, wenn ich in einem Software-Team arbeiten würde, welches auf Typsicherheit wert legen würde. 😉

    Die Realität sieht leider anders aus. 😞

    knivil schrieb:

    Gegenfrage: Von welchem Typ ist 42 hier:

    float ultimateAnswer = 42;
    

    Na? Es spielt keine Rolle, da der Compiler schlau ist und die Variable mit 42 als float belegt. Noch ne Gegenfrage: Von welchem Typ sind 234, 1, 6 oder 13? Sind sie natuerliche Zahlen, ganze, gebrochene, reele oder gar komplexe? Sie sind alles! Deswegen ist die Frage nach dem Typ von Zahlen eine schlecht gestellte Frage. Variablen haben Typen, Zahlen im allgemeinen nicht.


  • Administrator

    Viel bessere Fehler, warum man Makros nur mit grösster Vorsicht benutzen sollte:

    enum Type
    {
      NUMBER,
      TEXT,
      IMAGE,
      FILE
    };
    

    Tjo, das gibt einen äusserst seltsamen Kompilerfehler. Dem Präprozessor sind Scopes scheiss egal.

    Und auch einen weit bekannten blöder Fehler, ist der folgende:

    #include <windows.h>
    #include <limits>
    
    int main()
    {
      std::numeric_limits<int>::max();
    
      return 0;
    }
    

    max ist ein Makro in windows.h , was zu einem Fehler führt in diesem Code.

    Übrigens, die integer und floating point Literale sind im Standard so definiert, dass der Compiler eine freie Wahl, mit den folgenden Regeln:

    Sufix              Decimal constant             Octal or hexadecimal constant
    -------------------------------------------------------------------------------
    none               int                          int
                       long int                     unsigned int
                                                    long int
                                                    unsigned long int
    -------------------------------------------------------------------------------
    u or U             unsigned int                 unsigned int
                       unsigned long int            unsigned long int
    -------------------------------------------------------------------------------
    l or L             long int                     long int
                                                    unsigned long int
    -------------------------------------------------------------------------------
    Both u or U        unsigned long int            unsigned long int
    and l or L         
    -------------------------------------------------------------------------------
    
    Floating Point:
    1.
    .0
    1e1
    1.e2
    1.0e3
    sind alles doubles.
    
    Für float braucht es das Suffix f oder F:
    1.f
    .0f
    1e1f
    1.e2f
    1.0e3f
    
    Für long double braucht es das Suffix l oder L:
    1.l
    .0l
    1e1l
    1.e2l
    1.0e3l
    

    Ich hoffe ich habe jetzt nichts falsch abgeschrieben 🙂

    Grüssli



  • Naja, freie Wahl nun auch nicht. Die Regel ist IIRC mehr "nimm das erste aus der Liste, wo die Zahl reinpasst."



  • lord.hong schrieb:

    Stimmt, wenn ich in einem Software-Team arbeiten würde, welches auf Typsicherheit wert legen würde. 😉

    Die Realität sieht leider anders aus. 😞

    Was nicht bedeuten muss dass du es ihnen nachmachen und auf Typsicherheit verzichten musst.


Anmelden zum Antworten