unsigned wird in if-statement-Vergleichen signiert?

8

Ich habe diese Seite nach einer Antwort durchsucht und viele Antworten auf einen unsignierten / signierten Vergleich gefunden, aber dieses Problem besteht darin, dass nur vorzeichenlose Parameter verglichen werden, aber trotzdem funktioniert es lustig.

Das Problem mit dem folgenden Code ist, dass die erste if -stat nicht auftritt ("Hallo"), wo die zweite ("Welt") tut. Dies habe ich interpretiert, da die Berechnung, die innerhalb der if -statement durchgeführt wird, eine negative Zahl erzeugt, aber die exakt gleiche Berechnung, die mit dem in einer Variable gespeicherten Ergebnis durchgeführt wurde, nicht funktioniert (obwohl das Ergebnis in einer signierten Variable gespeichert wird).

Der verwendete Compiler ist gcc 4.4.

%Vor%

Kann jemand das für mich erklären und vielleicht eine Lösung für eine Korrektur finden, so dass die erste if -Anweisung auch funktioniert?

    
Wilmer 17.11.2010, 12:27
quelle

4 Antworten

4

Im Ausdruck:

%Vor%

(u16_varLow - u16_varHigh) wird zu einem int hochgestuft und zu -65525 ausgewertet. Die Lösung für Ihr Problem besteht darin, auf einen unsignierten Typ zu konvertieren, wie Sie es in dem "Wird eingeben" -Code tun.

Der Grund dafür, dass s16_Res1 = u16_varLow - u16_varHigh; 11 ergibt, ist, dass das Ergebnis der Subtraktion, -65525, nicht in einen Short passt.

    
Andreas Brinck 17.11.2010, 12:39
quelle
2

In den anderen Antworten haben wir das gesehen

%Vor%

für Sie (mit 16 bit short und 32 bit int ) entspricht

%Vor%

und somit sein Ergebnis ist int value -65525 . Also die Zuordnung

%Vor%

entspricht

%Vor%

was in Ihrem Fall von 16 bit short zu undefiniertem Verhalten führt. Sie haben nur Pech, dass Ihr Compiler stattdessen 11 zuweisen möchte. (Pech, weil ich denke, dass es besser ist, früh zu versagen.)

Im Gegensatz dazu

%Vor%

ist eine gültige Zuweisung, da u16_Res1 vom Typ ohne Vorzeichen ist und die Arithmetik von vorzeichenlosen Typen modulo mit der entsprechenden Potenz von zwei ist.

    
Jens Gustedt 17.11.2010 13:14
quelle
2

Bei den "üblichen arithmetischen Konvertierungen" werden Typen, die kleiner als int sind, entweder in int oder in unsigned int umgewandelt, bevor sie in den meisten Ausdrücken verwendet werden. Die Regel lautet: Wenn int alle Werte des kleineren Typs darstellen kann, wird sie zu int ; Andernfalls wird es zu unsigned int hochgestuft. Dies wird oft als eine Art Warze angesehen, da es in vielen Fällen dazu führt, dass die Werte unsigned char und unsigned short auf int hochgestuft werden.

Genau das sehen Sie - u16_varLow und u16_varHigh und (unsigned short)5 werden alle vor der Subtraktion und dem Vergleich zu int hochgestuft, was dann mit int geschieht. Wenn Sie sicher sein wollen, dass ein Ausdruck vorzeichenlose Arithmetik verwendet, müssen Sie dies in unsigned int , nicht unsigned short :

tun %Vor%     
caf 18.11.2010 04:05
quelle
1

Die erste, if( (u16_varLow - u16_varHigh) > (unsigned short)5 ) , wird niemals übergeben, da (u16_varLow - u16_varHigh) eine negative Zahl zurückgibt, weil sie als ganze Zahl behandelt wird. Die zweite wirft die gleiche negative Zahl, kurz vorzeichenlos, deshalb vergeht sie.

Hinweis - Sie wissen, dass dies plattformabhängig ist, oder? Die Größe von short , int usw. hängt von der konkreten Plattform ab.

    
Kiril Kirov 17.11.2010 12:40
quelle