int statt unsigned short - Wieso?



  • Manchmal nimmt man sie für qualifizierte Fehlermeldungen.

    bool f(int i)
    {
      if (i<0)
         throw LogigError("Du bist ein Weihnachtsmann!");
      if (i>10)) 
         throw LogigError("Du bist ein Osterhase!");
      return true;
    }
    


  • Der aus dem Westen... schrieb:

    ein char (mit Umwandlung, sodass er nicht als Buchstabe angesehen wird) noch mehr,

    Ein char brauchst du auch nicht umwandeln, das ist ja schon ein numerischer Typ. Und selbst wenn, in was würdest du ihn denn dann konvertieren? In ein int? 😉



  • Kann es evtl. auch daran liegen, dass der Compiler von Haus aus bei Zahlen von einem int ausgeht?

    main
    {
      f(5); // 5 ist int?
    }
    


  • stefanjann schrieb:

    Kann es evtl. auch daran liegen, dass der Compiler von Haus aus bei Zahlen von einem int ausgeht?

    Das gilt, solange du die Zahlen nicht speziell angibst (5ul bedeutet z.B. eine 5 [unsigned long]).



  • Mein Compiler hat sowieso einen an der Waffel. Entweder macht er nicht das, was ich will, oder er macht alles doppelt und dreifach. Sobald ich aber die MFC einbinde, läuft er sogar ganz gut. Komisch, nicht...

    Ja, es gibt nämlich Standartkonvertierungen.

    IrgendeineFunktion("Irgendein String");        // Typ ist char*
    IrgendeineFunktion((BYTE*)"Irgendein String"); // Typ ist BYTE*
    IrgendeineFunktion(L"Irgendein String");       // Type ist wchar_t*
    
    IrgendeineFunktion(1);           // Typ ist int
    IrgendeineFunktion((unsigned)1); // Typ ist unsigned int
    IrgendeineFunktion((USHORT)1);   // Typ ist USHORT
    

    Nur wenn man dem Compiler ganz genau sagt, wie er den Wert behandeln soll, gibt es keine Konvertierung.



  • Der aus dem Westen... schrieb:

    Ja, es gibt nämlich Standartkonvertierungen.

    ...

    Nur wenn man dem Compiler ganz genau sagt, wie er den Wert behandeln soll, gibt es keine Konvertierung.

    Doch, genau das machst du hier: Konvertieren (Teilweise unnötig, und zudem solltes du lieber wenn du konvertierst auf die C++ Casts zurückgreifen - sind sicherer). Wenn du Zahlen von haus aus richtig angibst (wie in meinen Beispiel 5ul für eine 5 [unsigned long]) gibt es keine Konvertierung zur Laufzeit mehr.



  • asc schrieb:

    Doch, genau das machst du hier: Konvertieren (Teilweise unnötig, und zudem solltes du lieber wenn du konvertierst auf die C++ Casts zurückgreifen - sind sicherer).

    Bockmist!
    foo(static_cast<char>(5)); ist nicht sicherer als foo(char(5)); oder foo((char)5);

    asc schrieb:

    Wenn du Zahlen von haus aus richtig angibst (wie in meinen Beispiel 5ul für eine 5 [unsigned long]) gibt es keine Konvertierung zur Laufzeit mehr.

    Genau so klug wie die erste These.
    foo((unsigned long)5); erzeugt keine Konvertierung zur Laufzeit.



  • volkard schrieb:

    Bockmist!
    foo(static_cast<char>(5)); ist nicht sicherer als foo(char(5)); oder foo((char)5);

    👍



  • volkard schrieb:

    asc schrieb:

    Doch, genau das machst du hier: Konvertieren (Teilweise unnötig, und zudem solltes du lieber wenn du konvertierst auf die C++ Casts zurückgreifen - sind sicherer).

    Bockmist!
    foo(static_cast<char>(5)); ist nicht sicherer als foo(char(5)); oder foo((char)5);

    Aber dies:
    IrgendeineFunktion((BYTE*)"Irgendein String");
    empfinde ich als Sicherheitsrisiko - wenn man sich nicht darauf verlässt das BYTE* gleich char* ist. Da sehe ich lieber wenn eine reinterpretierung statt findet.

    IrgendeineFunktion(reinterpret_cast<BYTE*>("Irgendein String"));
    

    volkard schrieb:

    Genau so klug wie die erste These.
    foo((unsigned long)5); erzeugt keine Konvertierung zur Laufzeit.

    Gut, wusste noch nicht das die C-Casts standardmäßig vom Compiler rausoptimiert werden. Weil die 5 hier erst einmal ein int-Wert ist, eine 5ul wäre ein unsigned long.



  • asc schrieb:

    Aber dies:
    IrgendeineFunktion((BYTE*)"Irgendein String");
    empfinde ich als Sicherheitsrisiko - wenn man sich nicht darauf verlässt das BYTE* gleich char* ist. Da sehe ich lieber wenn eine reinterpretierung statt findet.

    Ich auch.
    Aber wenn man dogmatisch alles mit <>-casts macht, wie Du es vorschlägst, schwächst Du die erwünsche Signalwirkung des reinterpret_cast doch nur ab.



  • _matze schrieb:

    volkard schrieb:

    Bockmist!
    foo(static_cast<char>(5)); ist nicht sicherer als foo(char(5)); oder foo((char)5);

    👍

    Auch: 👍



  • Zurück zum Thema:

    void book(int page) // oder unsigned short?
    {
      switch (page)
      {
      case 1: cout << .... break;
      case 2: cout << .... break;
      case 3: cout << .... break;
      default: cout << "Seite nicht vorhanden\n";
      }
    }
    
    int main()
    {
      book(1);
      book(3);
    }
    

    Was macht jetzt mehr Sinn? int oder unsigned short. Wenn ich euch richtig verstanden habe, dann eigentlich unsigned short, weil ich mir sicher bin, dass es ja keine negativen Zahlen geben wird und der Wertebereich sicherlich abgedeckt ist. Könnte ich diese Dinge nicht sicher stellen, dann int. Richtig verstanden?



  • Nimm int. damit ist alles am einfachsten. Unsigned nur, wenn negtive Zahlen stören würden



  • Du vergisst aber asc's Post:

    asc schrieb:

    int entspricht in der Regel dem Typ, mit dem der Rechner arbeitet (z.b. häufig 32 Bit auf ein 32 Bit-System und 64 bit auf einem 64-Bit System). Dies kann (muss aber nicht) gewisse Performancevorteile etc. mit sich bringen.

    Kann natürlich nur irgendwie merkliche Vorteile bringen, wenn man sich in rechenintensiven Routinen befindet (wenn überhaupt). Im Beispiel isses sowieso Pott wie Deckel. Es sei denn, du willst unbedingt die 2 Bytes sparen. Und Signed oder Unsigned ist im Beispiel doch auch egal. Im Speicher ist es dasselbe. Solange du nicht <>-Vergleiche machst oder so, macht's doch keinen Unterschied. Es kann aber quasi zur "Dokumentation" im Code beitragen. Wenn eine Funktion ein unsigned int verlangt, kommst du gar nicht erst auf die Idee, was Negatives zu übergeben.



  • volkard schrieb:

    Aber wenn man dogmatisch alles mit <>-casts macht, wie Du es vorschlägst, schwächst Du die erwünsche Signalwirkung des reinterpret_cast doch nur ab.

    Das "Aber wenn man dogmatisch alles mit <>-casts macht, wie Du es vorschlägst" habe ich niemals gesagt, sondern nur das ich statt C-Casts immer die C++ Pendants verwenden würde (Da ich danach auch suchen kann, bei C-Casts ist dies nicht eindeutig möglich).

    Ich würde an den meisten Stellen keinen Cast verwenden, wenn ich dies durch eine explizite Typangabe eh umgehen kann. Ich verwende statt "static_cast<unsigned long>(5)", "(unsigned long)5" oder "unsigned long(5)" einfach gleich die typisierte 5 ("5ul").



  • asc schrieb:

    oder "unsigned long(5)"

    Das geht ja genausowenig wie int*(0) für einen Nullzeiger auf int. 😉
    Es muss schon ein Wort sein. Sonst benutz ich aber auch mal gern die Funktions-Syntax für's statische Casting.

    Gruß,
    SP



  • asc schrieb:

    Das "Aber wenn man dogmatisch alles mit <>-casts macht, wie Du es vorschlägst" habe ich niemals gesagt, sondern nur das ich statt C-Casts immer die C++ Pendants verwenden würde (Da ich danach auch suchen kann, bei C-Casts ist dies nicht eindeutig möglich).

    Du nimmst möglichst immer die <>-casts. Aus prinzipiellen Gründen. Unabhängig vom Umfeld. Das ist doch Dogmatismus pur. Daß Du das innerhalb eines Satzes abstreitest und dann doch belegst, beleidigt meine Intelligenz.[/quote]

    Ich würde an den meisten Stellen keinen Cast verwenden, wenn ich dies durch eine explizite Typangabe eh umgehen kann. Ich verwende statt "static_cast<unsigned long>(5)", "(unsigned long)5" oder "unsigned long(5)" einfach gleich die typisierte 5 ("5ul").

    Ich sehe, daß Du noch nicht auf die einschlägigen Probleme damit gestoßen bist. Ich leuchte mal voraus:

    bool isprime(u16 n);//lookup and wheel
    bool isprime(u32 n);//additional SPRP
    bool isprime(u64 n);//more SPRP, result truth depending on riemann hypothesis
    ...
    cout<<isprime(u16(100));
    

    Welche typsuffixe nimmt man eigentlich für einen 16-bittigen unsigned int? welchen suffix für size_t?


  • Administrator

    asc schrieb:

    volkard schrieb:

    asc schrieb:

    Doch, genau das machst du hier: Konvertieren (Teilweise unnötig, und zudem solltes du lieber wenn du konvertierst auf die C++ Casts zurückgreifen - sind sicherer).

    Bockmist!
    foo(static_cast<char>(5)); ist nicht sicherer als foo(char(5)); oder foo((char)5);

    Aber dies:
    IrgendeineFunktion((BYTE*)"Irgendein String");
    empfinde ich als Sicherheitsrisiko - wenn man sich nicht darauf verlässt das BYTE* gleich char* ist. Da sehe ich lieber wenn eine reinterpretierung statt findet.

    IrgendeineFunktion(reinterpret_cast<BYTE*>("Irgendein String"));
    

    Da hätte ich jetzt irgendwie anders argumentiert:

    IrgendeineFunktion(static_cast<BYTE*>("Irgendein String"));
    

    Gibt einen Fehler, falls es unterschiedliche Zeiger sind. Daher eben auch sicherer.

    @volkard,
    Benutzt du eigentlich C++ Casts oder verfolgst du den Dogmatismus "Alles nur mit C Cast"? Wenn du C++ Casts verwendest: wann, wo und wieso?
    Würde mich jetzt mal interessieren.

    Grüssli



  • volkard schrieb:

    Du nimmst möglichst immer die <>-casts. Aus prinzipiellen Gründen.

    Ja, aus praktischen Gründen:
    (a) Suchmöglichkeit
    (b) Sicherheit
    (c) Konsistenz (Nicht mal C-Style Casts und dann C++ Casts)

    Und nur dort wo nötig. Sprich: wo man sie umgehen kann nicht. Und in den Beispielen hätte man sie weitgehend umgehen können.

    volkard schrieb:

    Daß Du das innerhalb eines Satzes abstreitest und dann doch belegst, beleidigt meine Intelligenz.

    Ich dachte eher es beleidigt deine Arroganz.

    Davon abgesehen ist es mir durchaus bekannt das es nicht für jeden Typ eine direkte Typisierung gibt, aber dort wo es sie gibt, kann man sie auch verwenden. Interessanterweise ist in meinen Programmen die Signalwirkung der C++ Casts dennoch vorhanden => Ich verwende so gut wie keine Casts in meinen Programmen...



  • Dravere schrieb:

    @volkard,
    Benutzt du eigentlich C++ Casts oder verfolgst du den Dogmatismus "Alles nur mit C Cast"? Wenn du C++ Casts verwendest: wann, wo und wieso?
    Würde mich jetzt mal interessieren.
    Grüssli

    ich verwende eigentlich gar keine c-casts.

    reinterpret_cast nehme ich immer, wenn ich was reinterpretiere. wegen der signalwirkung. zum beispiel zeiger in int für i32 hash(void*).
    dynamic_cast nehme ich eher in

    if(Foo* f=dynamic_cast<Foo*>(baseptr))
      f->machwas();
    

    um frühe Designfehler voll auszukosten.
    static_cast um in der klassenhierarchie downzucasten (kein witz, aber das hatten wir schon).
    const_cast eher nicht.
    c-casts eher nicht.
    function style casts ganz oft. wie einstellige konstruktoren auch. es wäre auch quatsch, da einen unterschied zu machen, finde ich.


Anmelden zum Antworten