Verstehe Warnung nicht: signed/unsigned-Konflikt



  • Hallo, bei folgendem Code wirft mir der Visual C++ Compiler eine Warnung in Zeile 3 (mit /W4)

    typedef unsigned char type;
    
    static const type type_max = ~((type)0u);
    

    Warnung:

    warning C4245: "Initialisierung": Konvertierung von "int" in "const type", signed/unsigned-Konflikt.
    

    Aber ich habe doch type explizit als unsigned deklariert, dazu das literal 0 als unsigned. Oder gibt der ~ Operator immer ein signed zurück??



  • IWish schrieb:

    Oder gibt der ~ Operator immer ein signed zurück??

    Nicht immer aaaber ...

    http://msdn.microsoft.com/de-de/library/dxt4z71k.aspx

    Im obigen Artikel wird dich vielleicht besonders der Hinweis/Link auf "Integral Promotions" interessieren.



  • hmpf schrieb:

    IWish schrieb:

    Oder gibt der ~ Operator immer ein signed zurück??

    Nicht immer

    Bitte genauer. Wann gibt ~(unsigned) einen signed zurück und wann nicht?



  • Auszüge aus dem C++-Standard:

    4.5, Integral promotions schrieb:

    An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int.

    13.6, Builtin operators schrieb:

    In this subclause, the term promoted integral type is used to refer to those integral types which are preserved by integral promotion (including e.g. int and long but excluding e.g. char).
    [...]
    For every promoted integral type T, there exist candidate operator functions of the form

    T operator˜(T);
    


  • Wenn ich das richtig verstanden habe, wird mein unsigned char durch den compl operator auf int promoted und dann wieder in ein unsigned char gespeichert. Da es sich aber um POD's handelt, verhält sich mein Code, so wie ich es mit vorstelle und ich kann die warnung ignorieren.
    Richtig?



  • IWish schrieb:

    und ich kann die warnung ignorieren.
    Richtig?

    japp. aber noch besser: du deaktivierst sie an dieser stelle:

    # pragma warning(push)
    # pragma warning(disable: xxxx) //kA, was die fehlermeldungs-nr ist...
    
      static unsigned max = ~0;
    
    # pragma warning(pop)
    

    da das im header (imho) wahnsinnig beim lesen stört, würd ich das in den source-code verschieben.

    bb



  • Einfacher und portabler wäre jedoch ein Cast, der sollte die Warnung auch umgehen. Vielleicht noch mit Kommentar, um die Sache verständlicher zu machen.



  • Danke für die schnelle hilfe! Eine Frage habe ich aber noch 😃

    unsigned long long s = 63;
    unsigned long long z = (unsigned long long)~0;
    if( z & ( 1u<<s ) )
        std::cout<<"JA";
    else
        std::cout<<"NEIN";
    

    Dabei bekomme ich eine Warnung für Zeile 3:

    warning C4334: "<<": Das Ergebnis der 32-Bit-Verschiebung wurde implizit in 64 Bits konvertiert. (War eine 64-Bit-Verschiebung vorgesehen?)
    

    Das Problem ist: Als Ergebnis wird mir "NEIN" ausgegeben.
    Wenn ich das Literal "1u" explizit nach unsigned long long caste, ist die Ausgabe "JA".
    Aber sollte das literal nicht implizit in den größeren Typ (also long long) gecastet werden? Muss ich jetzt all meine Literale umcasten, wenn long long im Spiel ist?



  • Beim Shift-Operator sieht alles ein wenig anders aus, das Ergebnis richtet sich nach dem linken Operanden (was auch sinnvoll ist, da sich die Anzahl verschobener Stellen meist in einer viel kleineren Grössenordnung befindet).

    13.6, Builtin operators, §17 schrieb:

    For every pair of promoted integral types L and R, there exist candidate operator functions of the form

    LR   operator%(L, R);
    LR   operator&(L, R);
    LR   operatorˆ(L, R);
    LR   operator|(L, R);
    L    operator<<(L, R);
    L    operator>>(L, R);
    

    where LR is the result of the usual arithmetic conversions between types L and R.

    Verwende anstelle des Casts die Literalsuffixe
    ** ll **für signed long long int ( long long ) und
    ** ull **für unsigned long long int ( unsigned long long ).

    Und nimm doch für s einen kleineren Datentypen. Selbst unsigned char reicht noch ein paar Jahrzehnte.



  • Danke Nexus, das wusste ich nicht!

    Jetzt sind erstmal alle Fragen geklärt :schland:


Anmelden zum Antworten