static_cast Verständnisproblem



  • @chris4cpp Vielen Dank für die Erklärung😃👍


  • Mod

    @Zhavok sagte in static_cast Verständnisproblem:

    Weil zwischen Zahlen und Zeichen unterschieden wird. Mit Zahlen zum Beispiel kannst du Rechnen. 5 + 3 zum Beispiel. Allerdings kannst du ja nicht ! + % rechnen. Nun sind allerdings nicht nur Sonderzeichen "Zeichen" sondern trotzdem auch alle Zahlen. Mit einer 5 als Zahl kannst du also Rechnen. Mit einer 5 als Zeichen nicht. Für diese ganzen Zeichen gibt es eine Tabelle. Die ASCII Tabelle. Für jedes Zeichen gibt es eine Art ID. Folgendes bededeutet:

    c = static_cast<char>(66);
    

    c = Umwandlung von Zahl 66 in ein Zeichen.
    Du erhälst also das Zeichen was an der 66. Stelle in der Tabelle steht. Google einfach mal nach ASCII und schau dir die Bilder an. Dann siehst du die Tabelle. Auf Seite 78 kommt ja die for-Schleife dran. Wenn du soweit bist könntest du dir ein Programm schreiben, was alle Zeichen der Tabelle ausgibt. Ein Ausschnit der Ausgabe könnte also so aussehen:

    65 = A
    66 = B
    67 = C
    

    Ich bin mir nicht sicher ob du das richtige meinst und dich ungeschickt ausdrückst, oder ob du einfach Quatsch schreibst. Der wichtige Punkt ist nämlich, dass nicht zwischen Zahlen und Zeichen unterschieden wird! Zeichen sind im Computer nur Zahlen und entsprechend kann damit gerechnet werden. '!' + '%' ist in C++ ein wohldefinierter Ausdruck und das Ergebnis ist nicht "!%", weil da eben keine Sonderbedeutung für Zeichen existiert. Die ganze Interpretation, was ein Zeichen oder was eine Zahl ist, kommt ganz allein bei der Ausgabe zustande, durch die Wahl der passenden Ausgabefunktion. Bei C++ geschieht das dank Funktionsüberladung ein bisschen versteckt, da stillschweigend angenommen wird, dass char wohl als Zeichen interpretiert werden soll, aber in C sieht man noch ziemlich gut, was passiert:

    int i = 66;
    char c = 'B';
    
    printf("%c %c\n", i, c);
    printf("%d %d\n", i, c);
    

    Mit explizitem Hinweis, dass das 100% korrektes C ist, da muss man nix casten oder so, denn i und c sind aus Sicht des printf-Aufrufs beides Integertypen, printf entscheidet nur anhand des Formatstrings, was es jeweils daraus macht.



  • SeppJs Darstellung ist etwas verkürzt. Sie gilt nur für Zahlen im Wertebereich von char. Es wird schon zwischen Zahlen und Zeichen unterschieden - es kommt auf den Blickwinkel an. Wenn man sich Bitmuster im Speicher ansieht, ist die Bedeutung nicht ohne weiteres klar, auch wenn jedes Bitmuster natürlich als Zahl interpretiert werden kann. In einem Programm kommt die Interpretation, was ein Zeichen oder eine Zahl ist, nicht nur "ganz allein bei der Ausgabe zustande", sondern genau dafür ist der Datentyp da. Eine Typumwandlung static_cast<char>(66) bedeutet einfach nur, das der Zahl 66 zugeordnete Bitmuster als Zeichen vom Typ char zu interpretieren. Auch ist in C und C++ der Wertebereich der beiden Typen char und int unterschiedlich. Wenn nicht zwischen Zahlen und Zeichen unterschieden würde, müsste ja das C-Programm

    int i = 666;    // Wertebereich von char überschritten
    char c = i;
    int ic = c;
    printf("%d %d\n", i, ic);
    

    dasselbe liefern. Tut es aber nicht.



  • @Schnuffi

    Und Zahlen sind alle int?



  • @Schnuffi sagte in static_cast Verständnisproblem:

    In einem Programm kommt die Interpretation, was ein Zeichen oder eine Zahl ist, nicht nur "ganz allein bei der Ausgabe zustande"

    Wetten?

    @Schnuffi sagte in static_cast Verständnisproblem:

    Auch ist in C und C++ der Wertebereich der beiden Typen char und int unterschiedlich. Wenn nicht zwischen Zahlen und Zeichen unterschieden würde, müsste ja das C-Programm

     int i = 666;    // Wertebereich von char überschritten
     char c = i;
     int ic = c;
     printf("%d %d\n", i, ic);
    

    dasselbe liefern. Tut es aber nicht.

    Hm, C. Welchen Typ hat denn der Literal 'A' in C?

    Zeile 3 von Deinem Code ist sowohl in C und C++ implementation-defined (für C++ bis incl. C++17)

    C++17 aus [conv.integral]/3:

    If the destination type is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined.

    C17 §6.3.1.3/3:

    Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.


  • Mod

    @Schnuffi Ich weiß nicht, ob du es wirklich verstanden hast. char ist ein kleinerer int, genauso wie short. Ansonsten ist da, außerhalb der Ausgabefunktionen, nichts besonderes dran. Es ist ein ganz normaler Ganzzahldatentyp, wie jeder andere Ganzzahldatentyp auch, mit genau den gleichen Regeln, wie für alle anderen auch. Das kannst du nicht wegdiskutieren, das steht im Sprachstandard so geschrieben, §3.9.1 lässt da keinen Interpretationsspielraum, dass char Typen allesamt ganz normale Integer sind. Sie haben bloß die Zusatzanforderung, dass sie zusätzlich noch als Zeichen interpretierbar sein müssen. Die Interpretation erfolgt aber erst bei Ein- und Ausgaben, bzw. umgekehrt bei der Interpretation von Literalen.

    (Ein kleiner Unterschied zu anderen Integertypen ist noch, dass vom Standard nicht vorgegeben wird, ob char signed ist oder nicht.)

    Wenn du deine eigene Aussage auf short los lässt, merkst du wie unlogisch sie ist, denn dann hättest du gezeigt, dass shorts keine Zahlen sind.



  • @Swordfish sagte in static_cast Verständnisproblem:

    @Schnuffi sagte in static_cast Verständnisproblem:

    In einem Programm kommt die Interpretation, was ein Zeichen oder eine Zahl ist, nicht nur "ganz allein bei der Ausgabe zustande"

    Wetten?

    #include <iostream>
    using namespace std;
    
    void f(char c) {
       cout << "char:" << c << '\n';
    }
    
    void f(int i) {
       cout << "int:" << i << '\n';
    }
    
    int main () {
      f('a');
      f(1);
    }
    

    char, short und int sind integrale Typen, insofern Zahlen. Das ist bekannt und allen gemeinsam. Sie haben aber auch verschiedene Eigenschaften, ausgedrückt durch verschiedene Typen. Deswegen gilt zwar "ein Zeichen ist eine Zahl", aber die Umkehrung "eine Zahl ist ein Zeichen" gilt nicht allgemein. Deswegen ist es falsch zu schreiben" Der wichtige Punkt ist nämlich, dass nicht zwischen Zahlen und Zeichen unterschieden wird!". Zahlen ist ein allgemeiner Begriff, und char, short und int sind besondere Ausprägungen, die in C++ unterschieden werden, siehe Funktion f() oben.



  • @Schnuffi Du hast die Wette verloren. Das zeigt bloß was function overloading ist.

    Nochmal:

    @Swordfish sagte in static_cast Verständnisproblem:

    Hm, C. Welchen Typ hat denn der Literal 'A' in C?



  • @Swordfish Ja eben. Wie jeder sehen kann, zeigt function overloading, dass der Compiler hier sehr wohl zwischen char und int unterscheidet, nicht nur bei der Ausgabe, wie von dir behauptet.

    Der Typ von 'A' ist eine Zeichenkonstante des Typs int in C (ohne Multibyte-Zeichen), aber darum geht es hier nicht, wenn Du genauer liest. Die Frage geht an der besprochenen Problemstellung vorbei. Ein char in C muss nur groß genug sein, Elemente des Zeichensatzes zu enthalten, wie auch in C++, wo der Typ char ist (ohne Multibyte-Zeichen). Deswegen können char-Werte zwar in sinnvolle int-Werte konvertiert werden, das Umgekehrte gilt jedoch nicht zwingend. Müsste eigentlich klar sein.


  • Mod

    @SeppJ sagte in static_cast Verständnisproblem:

    Wenn du deine eigene Aussage auf short los lässt, merkst du wie unlogisch sie ist, denn dann hättest du gezeigt, dass shorts keine Zahlen sind.

    Gilt nach wie vor.

    Keine deiner Aussagen zeigt einen Unterschied zwischen Zeichen und Zahlen.



  • @Schnuffi Zu Deinem Code oben noch:

    Der Zeigt nur was function overloading ist. Das funktioniert für jeden x-beliebigen Typ und ist nix was irgendwie mit "ein char IST ein Zeichen" zu tun hätte. Schätzungsweise ruft der überladene std::ostream& operator<<(std::ostream&, char c) einfach rdbuf()->sputc(c) auf, was seinerseits den Wert von c über Betriebssystemmittel dann mit Deinem Lieblingsfont malt (oder im einfacheren Fall in den Grafikspeicher schreibt). Beim letzten Schritt wird daraus ein Zeichen.


Anmelden zum Antworten