2014-07-10 15 views
8

Ich versuche einen Test zu machen, um zu sagen, ob mein PC arithmetische oder logische Rechtsverschiebung durch Rechtsverschiebung hexadezimal FFFFFFFF von 1 ausführt.Warum erzeugen -1 >> 1 und 0xFFFFFFFF >> 1 unterschiedliche Ergebnisse?

Ich weiß, dass eine ganze Zahl -1 als FFFFFFFF in hexadezimale liest, da es das Komplement ist zwei 1. Right-shifting -1 von 1 Ergebnisse in FFFFFFFF und zeigt den PC arithmetische Rechtsverschiebung durchgeführt.

Aber wenn ich nur 0xFFFFFFFF >> 1 eintippe, ergab es 7FFFFFFF und zeigt, dass der PC logische Rechtsverschiebung statt. Warum ist das passiert? Sehen Sie den Code unten, dass die Ergebnisse produziert:

#include <stdlib.h> 
#include <stdio.h> 

int main (int argc, char *argv[]) 
{ 
    printf ("%x >> 1 = %x\n", -1, -1 >> 1); 
    printf ("%x >> 1 = %x\n", 0xffffffff, 0xffffffff >> 1); 

    return EXIT_SUCCESS; 
} 

Die Ausgabe des Programms war:

ffffffff >> 1 = ffffffff 
ffffffff >> 1 = 7fffffff 
+3

'-1' ist signiert. '0xffffffff' ist nicht signiert. Es hat nichts mit 'printf()' zu tun. – chux

+0

Rechtsverschiebung negative vorzeichenbehaftete Werte ist die Implementierung definiert: '-1 >> 1 'könnte auch als' 7fffffff 'drucken. – chqrlie

Antwort

7

Es ist keine Annahme. Was Typ denkst du 0xffffffff ist? Gemäß dem Standard-C, 6.4.4.1 ganzzahlige Konstanten, den Typ der Expression eines hexadezimalen Konstante (mit 0x voran) die ersten der folgenden ist die applicably den dargestellte Wert halten kann:

int 
unsigned int 
long int 
unsigned long int 
long long int 
unsigned long long int 

Auf Ihrer Plattform kann 0xFFFFFFFF nicht als int dargestellt werden, da int 32 Bit ist und nur 31 Bits die Menge in signed int ausdrücken (der Standard schreibt vor, dass ein Bit für das Zeichen reserviert ist). Der nächste Typ, unsigned int, wird daher verwendet. Daher ist kein Zeichenbit vorhanden, das mit der Schiebeoperation erweitert wird, die dadurch logischer statt arithmetisch ist.

Es kann nicht offensichtlich sein, wie ich folgerte int war 32 Bits auf Ihrer Plattform. Tatsächlich konnte ich diese Annahme nicht machen, wäre da nicht die erste Zeile, die arithmetisch-rechts-verschiebt den Wert -1. Das Ergebnis dieser Verschiebung, entsorgt als %x, war 0xFFFFFFFF. Hatte int waren native 64-Bit, die stattdessen 0xFFFFFFFFFFFFFFFF dump sollte. Ohne dieses Vorwissen könnte keine einzelne Typschlussfolgerung von 0xFFFFFFFF angenommen werden, da sie gut als ein Standard signierter int mit einer Breite von 64 Bits (63 + 1) mit einem Wert von 0x00000000FFFFFFFF darstellbar sein könnte.Die resultierende Verschiebung würde die gleiche Ausgabe erzeugen, die Sie jetzt sehen, wodurch eine Alternative zu der oben vorgeschlagenen eingeführt wird.

6

Ihre wichtigste Frage ist: ist 0xffffffff unsigned?

Von C11 §6.4.4.1 ganzzahlige Konstanten

Der Typ eines Integer-Konstante die erste von der entsprechenden Liste ist, in dem sein Wert dargestellt werden.

enter image description here

Der Ausgang der ersten printf Linie legt nahe, dass int 32-Bit auf Ihrem Rechner ist. Daher kann es 0xffffffff nicht darstellen, es muss nicht signiert sein.

+0

Es gibt in diesem Graphen nichts, was dazu führt, dass 0xffffffff 'unsigned' ist. Es ist OPs "-1", die die Schlussfolgerung antreibt. – chux

+0

@chux Ich verstehe deinen Standpunkt und du hast Recht. Aber ich denke nicht, wenn OP fragt, ob es eine vorzeichenlose ganze Zahl ist, meint er genau den Typ "unsigned" (d. H. "Unsigned int"). Ich denke, er meint die unsignierten Typen im allgemeinen, d. H. "Unsigned int", "unsigned long" oder "unsigned long long". Deshalb habe ich nicht das Code-Format * 'unsigned' *, nur * unsigned * verwendet. –

+0

'0xffffffff' könnte' int' sein (aka 'signed int') sollte' int' 64-bit sein. Angesichts der C-Spezifikation. '0xffffffff' muss' int', 'unsigned int',' long int' oder 'unsigned long int' sein. – chux

Verwandte Themen