Frage

Ich versuche zu konvertieren 65529 von einem unsigned int zu einem signierten int. Ich habe versucht, eine Besetzung wie diese zu machen:

unsigned int x = 65529;
int y = (int) x;

Aber y kehrt immer noch 65529 zurück, wenn es -7 zurückkehren sollte. Warum ist das so?

War es hilfreich?

Lösung

Es scheint, als würden Sie es erwarten int und unsigned int eine 16-Bit-Ganzzahl sein. Das ist anscheinend nicht der Fall. Höchstwahrscheinlich ist es eine 32-Bit-Ganzzahl-die groß genug ist, um die von Ihnen erwarteten Wrack-Abhänge zu vermeiden.

Beachten Sie, dass es keine vollständig konforme Möglichkeit gibt, dies zu tun, da das Casting zwischen signiert/unsigniert für Werte außerhalb des Bereichs implementiert ist. Dies wird jedoch in den meisten Fällen immer noch funktionieren:

unsigned int x = 65529;
int y = (short) x;      //  If short is a 16-bit integer.

oder alternativ:

unsigned int x = 65529;
int y = (int16_t) x;    //  This is defined in <stdint.h>

Andere Tipps

Ich weiß, dass es eine alte Frage ist, aber es ist gut. Wie wäre es damit?

unsigned short int x = 65529U;
short int y = *(short int*)&x;

printf("%d\n", y);

@Mysticial hat es verstanden. Ein kurzer Kurzschluss ist normalerweise 16-Bit und veranschaulicht die Antwort:

int main()  
{
    unsigned int x = 65529;
    int y = (int) x;
    printf("%d\n", y);

    unsigned short z = 65529;
    short zz = (short)z;
    printf("%d\n", zz);
}

65529
-7
Press any key to continue . . .


Ein bisschen mehr Detail. Es geht darum, wie signierte Zahlen im Speicher gespeichert werden. Suchen Sie nach zweifelsbetriebener Notation, um weitere Details zu erhalten, aber hier sind die Grundlagen.

Schauen wir uns also 65529 Dezimal an. Es kann als dargestellt werden als FFF9h in Hexadezimal. Wir können das auch in Binärer als:

11111111 11111001

Wenn wir deklarieren short zz = 65529;, Der Compiler interpretiert 65529 als signierter Wert. In zweier Bestimmungen bedeutet das obere Bit, ob ein signierter Wert positiv oder negativ ist. In diesem Fall können Sie sehen, dass das obere Bit a ist 1, so wird es als negative Zahl behandelt. Deshalb druckt es aus -7.

Für ein unsigned short, Es interessiert uns nicht um das Zeichen, seit es ist unsigned. Also, wenn wir es verwenden %d, Wir verwenden alle 16 Bits, also wird es als interpretiert als 65529.

Um zu verstehen, warum Sie wissen müssen, dass die CPU signierte Zahlen mithilfe der Komplement der beiden darstellt (vielleicht nicht alle, aber viele).

    byte n = 1; //0000 0001 =  1
    n = ~n + 1; //1111 1110 + 0000 0001 = 1111 1111 = -1

Und auch, dass der Typ in INT und das nicht signierte int je nach CPU unterschiedlich groß sein kann. Bei solchen spezifischen Sachen:

   #include <stdint.h>
   int8_t ibyte;
   uint8_t ubyte;
   int16_t iword;
   //......

Die Darstellung der Werte 65529U und -7 ist für 16 -Bit -INTs identisch. Nur die Interpretation der Bits ist anders.

Für größere INTs und diese Werte müssen Sie sich erweitern. Ein Weg ist mit logischen Operationen

int y = (int )(x | 0xffff0000u); // assumes 16 to 32 extension, x is > 32767

Wenn Geschwindigkeit kein Problem ist oder die Kluft auf Ihrem Prozessor schnell ist, ist es schnell.

int y = ((int ) (x * 65536u)) / 65536;

Die Multiplikum verschiebt 16 Bit (erneut unter der Annahme von 16 bis 32 Verlängerung) und die Kluft schaltet das Schild rechts auf.

Sie erwarten, dass Ihre int Der Typ ist 16 Bit breit. In diesem Fall würden Sie tatsächlich einen negativen Wert erhalten. Aber höchstwahrscheinlich ist es 32 Bit breit, also ein unterschrieben int kann 65529 gut darstellen. Sie können dies durch Drucken überprüfen sizeof(int).

Um die im obigen Kommentar veröffentlichte Frage zu beantworten - probieren Sie so etwas aus:

unsigned short int x = 65529U;
short int y = (short int)x;

printf("%d\n", y);

oder

unsigned short int x = 65529U;
short int y = 0;

memcpy(&y, &x, sizeof(short int);
printf("%d\n", y);

Da die Konvertierung unsigned -Werte zur Darstellung positiver Zahlen, die konvertiert werden, kann dies durchgeführt werden, indem das signifikanteste Bit auf 0 festgelegt wird. Daher interpretiert ein Programm dies nicht als Ergänzungswert von zwei. Eine Einschränkung ist, dass dies Informationen für Zahlen verliert, die in der Nähe von Max des nicht signierten Typs sind.

template <typename TUnsigned, typename TSinged>
TSinged UnsignedToSigned(TUnsigned val)
{
    return val & ~(1 << ((sizeof(TUnsigned) * 8) - 1));
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top