c++ Datentypen



  • #include <iostream>
    using namespace std;

    void main(void)
    {

    short Zahl;
    cin >> Zahl;

    if (Zahl > 30000)
    {
    typedef int Zahl;
    }

    cout << Zahl << endl;
    system ("Pause");
    }

    Wie ihr seht, versuche ich gerade ein Programm zu optimieren.
    Ich will wenn die eingegebene Zahl größer als 30000 den Datentyp automatisch in einen Integer umwandeln. Um Speicherplatz zu spare, bleibt der Datentyp bein einer Eingebenen zahl von weniger als 30000 short.
    Wenn ich bei diesem Programm aber eine Zahl eingebe die größer als 30000 ist bleibt der Datentyp trotzdem bei short. Was muss ich änder?



  • Du kannst den Typ einer Variablen nicht ändern.



  • volkard schrieb:

    Du kannst den Typ einer Variablen nicht ändern.

    Das ist, wie du bestimmt weisst nicht die ganze Wahrheit. 😉

    Der statische Typ lässt sich nicht ändern, den dynamischen, welchen wir bei Polymorphen Objekten haben aber sehr wohl.

    struct base
    {
    };
    
    struct child1 : base
    {};
    
    struct child2 : base
    {};
    
    ..
    
    child1 c1;
    child2 c2;
    
    base* b = c1;
    if ( ... )
      b = c2;
    


  • drakon schrieb:

    volkard schrieb:

    Du kannst den Typ einer Variablen nicht ändern.

    Das ist, wie du bestimmt weisst nicht die ganze Wahrheit. 😉

    Es bleibt in Deinem Beispiel ein Zeiger auf base.
    Ich weiß auch nicht so recht, was der Dynamische Typ einer Variablen ist.

    Edit: Ah, habs nachgelesen.

    int i;
    void* p=&i;
    

    Jetzt hat p den statischen Typ "Zeiger auf void" den dynamischen Typ "int".

    double d;
    int i=reinterpret_cast<int>(&p);
    

    Jetzt hat i den statischen Typ "int" und den dynamischen Typ "double".

    Faszinierend.

    edit2: Auch falsch. Das gilt ja nur bei polymorphen Typen.



  • c++lernerbrauch hilfe schrieb:

    Wie ihr seht, versuche ich gerade ein Programm zu optimieren.

    Wie wir sehen, versuchst du gerade, C++ auf eine Weise zurechtzubiegen, die dir nicht einmal wirklich eine Optimierung bringt.

    Sehr sinnvoll ist das nicht, was du da probierst. Du könntest natürlich über void* eine Frickellösung hinkriegen, mit der du nur den nötigen Speicher für die Zahl anforderst. Bezüglich Optimierung geht der Schuss dann aber gewaltig nach hinten los, da du statt der eingesparten 2 Bytes nun 4 zusätzliche für den Zeiger brauchst und du eine langsame Heap-Allokation hast.

    Also kurz gesagt: Nimm ruhig einen int , auch wenn der Wertebereich nicht voll ausgenutzt wird.



  • volkard schrieb:

    drakon schrieb:

    volkard schrieb:

    Du kannst den Typ einer Variablen nicht ändern.

    Das ist, wie du bestimmt weisst nicht die ganze Wahrheit. 😉

    Es bleibt in Deinem Beispiel ein Zeiger auf base.

    Ja. Der statische Typ, aber der dynamische ist der des abgeleiteten Objektes, auf welches er zeigt. Und den kann man ja bekannterweise ändern.

    1.3.3 dynamic type [defns.dynamic.type]
    the type of the most derived object (1.8) to which the lvalue denoted by an lvalue expression refers. [Example:
    if a pointer (8.3.1) p whose static type is “pointer to class B” is pointing to an object of class D, derived
    from B (clause 10), the dynamic type of the expression *p is “D.” References (8.3.2) are treated similarly. ]
    The dynamic type of an rvalue expression is its static type.



  • Weils mir gerade einfällt:

    drakon schrieb:

    struct base
    {
    };
    
    struct child1 : base
    {};
    
    struct child2 : base
    {};
    
    child1 c1;
    child2 c2;
    
    base* b = &c1;
    if ( ... )
      b = &c2;
    

    was würde decltype hier machen?

    child1 c1; //decltype(c1) == child1
    child2 c2; //decltype(c2) == child2
    
    base* b = &c1;
     //decltype(b) == base* ?
     //decltype(*b) == child1 ?
    

    bb



  • decltype arbeitet ja auf Kompilierebene, also würde ich sagen, dass es zweimal base* gibt.



  • drakon schrieb:

    decltype arbeitet ja auf Kompilierebene, also würde ich sagen, dass es zweimal base* gibt.

    auch bei decltype(*b) ? Oo

    bb



  • unskilled schrieb:

    drakon schrieb:

    decltype arbeitet ja auf Kompilierebene, also würde ich sagen, dass es zweimal base* gibt.

    auch bei decltype(*b) ? Oo

    bb

    Ne, sorry. Da würde ich sagen base .

    Den tatsächlichen Typen kann man zur Kompilierzeit ja nicht feststellen. (ginge wahrscheinlich mit Typenanalyse zum Teil schon, aber das ist ein anderes Thema.. :))



  • unskilled schrieb:

    auch bei decltype(*b) ? Oo

    ja.



  • struct base {};
    struct child1 : base {};
    struct child2 : base {};
    

    unskilled schrieb:

    was würde decltype hier machen?

    child1 c1; //decltype(c1) == child1
    child2 c2; //decltype(c2) == child2
    base* b = &c1;
     //decltype(b) == base* ?
     //decltype(*b) == child1 ?
    
    decltype(b)    steht für base*
    decltype((b))  steht für base*&
    decltype(*b)   steht für base&
    

    Es wird zwischen Bezeichner und Ausdruck unterschieden. decltype liefert den deklarierten Typ des Bezeichners oder den "Rückgabetypen" eines Ausdrucks. Andere Beispiele:

    struct foo {
      int j;
    };
    foo const& f = ...;
    
    decltype(f)     --> Deklarierter Typ des Bezeichners f ist [b]foo const&[/b]
    decltype(f.j)   --> Deklarierter Typ des Bezeichners foo::j ist [b]int[/b]
    decltype((f.j)) --> "Typ des Ausdrucks" f.j ist [b]int const&[/b]
    

    Da fragt man sich zunächst, ob das wirklich alles so sinnvoll ist. Ich habe mich aber inzwischen damit angefreundet.

    (Angaben ohne Gewähr)

    edit: Ich habe es nochmal nachgeguckt. Es gibt vier Fälle.
    (1) nicht-geklammerten Bezeichner oder Elementzugriff --> decltype liefert den deklarierten Typ.
    (2) andernfalls, Funktionsaufruf --> decltype liefert den Rückgabetyp der Funktion
    (3) andernfalls, Lvalue-Ausdruck --> decltype liefert eine entsprechende Lvalue-Referenz.
    (4) andernfalls --> decltype liefert den Typ des Ausdrucks.

    Gruß,
    SP



  • Danke SP : >

    bb


Anmelden zum Antworten