Rechts-shift mit Nullen am Anfang
Ich versuche zu tun, eine Art Verschiebung nach Links, das wäre Nullen, die am Anfang anstelle von ones. Wenn ich beispielsweise die linke shift -0xff
, bekomme ich diese:
0xff << 3 = 11111000
Allerdings, wenn ich rechts verschieben, bekomme ich diese:
0xff >> 3 = 11111111
Gibt es eine operation, die ich verwenden könnte, um das äquivalent von einer Verschiebung nach Links? also ich würde gerne dieses:
00011111
Jede Anregung?
Bearbeiten
Antwort auf die Kommentare, hier ist der code, den ich verwende:
int number = ~0;
number = number << 4;
std::cout << std::hex << number << std::endl;
number = ~0;
number = number >> 4;
std::cout << std::hex << number << std::endl;
Ausgabe:
fffffff0
ffffffff
Da es scheint, dass im Allgemeinen sollte es funktionieren, ich bin interessiert, warum dieser bestimmten code nicht. Irgendeine Idee?
- Diese Frage macht keinen Sinn. Sollten Sie nicht das Ergebnis bekommen, das Sie beschreiben, auf einen C-compiler. Poste bitte den aktuellen code.
- Die
0xff << 3
geben sollte11111111000
Und die0xff >> 3
geben sollte11111
- Das ist nicht wahr! Wenn der Wert ein Vorzeichen, das ist eigentlich ein korrektes Verhalten gemäß dem C-standard (effektiv, das Vorzeichen-bit wird beibehalten.) Es ist eine Implementierung konkreten Fall.
- Nein... die Literale in der Frage vom Typ integer, mit Vorzeichen, aber Sie wird positiv sein. Kein Zeichen-bits gesetzt sind, ist nichts negatives. Der C-standard ist nur besorgt, ob der integer negativ ist oder nicht. C11 6.5.7/4 (Links-shift)
"If E1 has a signed type and nonnegative value..." "...otherwise, the behavior is undefined."
C11 6.5.7/5 (right shift)"If E1 has a signed type and a negative value, the resulting value is implementation-defined."
- der Grund, es ist keine Implementierung-definiert ist, dass
INT_MAX
ist garantiert mindestens 2^16-1. So0xff
ist ein positiver Wert des Typsint
, und es kann nach Links verschoben werden, die durch 3 ohne überschreitungINT_MAX
. Was der Fragesteller beschreibt, ist nicht konform Verhalten, also entweder es ist nicht das, was sein code hat wirklich sonst seine compiler kaputt. - Hrm, Ihr seid richtig. Ich dachte (bei 5somethingAM), die
0xff
wäre einsigned char
aber offensichtlich ist das falsch. Ich mich zurückziehe, meine Vorherige Aussage. Kaffee, dann etwas verschieben. - Ich habe bereits meine Frage mit Beispiel-code. Ich bin mit C++, und getestet mit gcc und msvc. Bin ich etwas fehlt?
- bitte sehen Sie sich den Beispiel-code, den ich verwende.
~0
ist nicht gleich0xff
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist, wie C und binäre Arithmetik beide arbeiten:
Wenn du mit der linken shift
0xff << 3
bekommen Sie binäre:00000000 11111111 << 3 = 00000111 11111000
Wenn Sie mit der rechten shift -
0xff >> 3
bekommen Sie binäre:00000000 11111111 >> 3 = 00000000 00011111
0xff
ist ein (signed) int mit dem positiven Wert255
. Da ist es positiv, das Ergebnis der Verschiebung ist es wohl definiert Verhalten in C und C++. Es wird nicht eine beliebige arithmetische Verschiebungen noch irgendeine Art oder schlecht-definierten Verhalten.Ausgabe:
Damit Sie etwas seltsames in Ihrem Programm, weil es nicht funktioniert wie erwartet. Vielleicht sind Sie mit char-Variablen oder C++ - Zeichen-Literale.
Quelle: ISO 9899:2011 6.5.7.
EDIT nach Frage update
int number = ~0;
gibt Sie eine negative Zahl entspricht -1, vorausgesetzt, Zweierkomplement.number = number << 4;
ruft Undefiniertes Verhalten, da Sie Links-shift einer negativen Zahl. Das Programm implementiert Undefiniertes Verhalten korrekt, da Sie entweder etwas tut, oder gar nichts. Es kann drucken fffffff0 oder möglicherweise drucken Sie ein rosa Elefant, oder es kann die Festplatte formatieren.number = number >> 4;
ruft in der Implementierung definierte Verhalten. In deinem Fall, dein compiler behält das Vorzeichen-bit. Dies ist bekannt als arithmetic shift, und die arithmetische rechts-Verschiebung funktioniert so, dass der MSB ist gefüllt mit was auch immer-bit-Wert, den es hatte, bevor die Verschiebung. Also, wenn Sie eine negative Zahl, werden Sie erleben, dass das Programm "verschieben in".In 99% aller realen Welt Fällen ist es nicht sinnvoll zu verwenden von bit-Operatoren auf zahlen signiert. Daher immer sicherstellen Sie, dass Sie zahlen ohne Vorzeichen, und dass keines der gefährlichen implizite konvertierungsregeln in C/C++ wandelt Sie in zahlen unterzeichnet (für weitere Informationen über gefährliche Konvertierungen finden Sie unter "die integer-promotion-Regeln" und "die üblichen arithmetischen Umwandlungen", viele gute info über diese auf SO).
EDIT 2, einige Infos aus dem C99-standard ist die Begründung V5 Dokument.10:
Wenn Sie explicitilhy shift 0xff, es funktioniert wie erwartet
Sollte es nur möglich sein, wenn
0xff
ist in der Art, signiert, Breite 8 (char
undsigned char
auf gängigen Plattformen).So, in gemeinsamer Fall:
Müssen Sie verwenden Sie unsigned ints
(unsigned type)0xff
Rechte shift arbeitet als division durch 2(mit Rundung nach unten, wenn ich das richtig verstanden habe).
So, wenn man 1 als erstes bit haben Sie negative Wert und nach der Teilung ist es negative wieder.
0xffu
Werken statt des cast.0xff
nur, wenn Sie in einemsigned char
geben - sonst0xff
hat einen nicht-negativen Wert (255). Ich denke, dies sei ausdrücklich erwähnt, denn ich habe Menschen gesehen, die verwirrt und denken, dass0xff
hat einen negativen Wert in Kontexten, wo es nicht.Den beiden Arten von rechts-shift denen du sprichst, sind sogenannte Logische Verschiebung und Arithmetic Shift. C und C++ Einsatz von logischen shift für vorzeichenlose Ganzzahlen und die meisten Compiler verwenden arithmetische Verschiebung für eine Ganzzahl, aber das ist nicht garantiert durch die Norm Bedeutung, dass der Wert des rechts verschieben einer negativen signed int ist, ist die Implementierung definiert.
Da Sie eine logische Verschiebung, die Sie wechseln müssen, um über eine vorzeichenlose Ganzzahl. Sie können dies tun, indem Sie den Ersatz Ihres Konstanten mit
0xffU
.Zu erklären, Ihre echten code, den Sie müssen nur den C++ - Versionen der Zitate aus dem C-standard, dass Lundin gab in den Kommentaren:
Undefiniertes Verhalten. [expr.shift] sagt
Implementierung-definiert das Ergebnis, in diesem Fall Ihrer Umsetzung gab Sie einen arithmetischen shift:
Sollten Sie eine unsigned Typ:
Ausgabe:
Meine 5 Cent hier...
Ich stehe vor genau dem gleichen problem wie dieses.lau! Ich habe einige oberflächliche Forschung auf dies und das sind meine Ergebnisse:
Scheint es (in Ermangelung jemand mit detaillierten Kenntnissen), dass der C-compiler in XCode für Mac OS X v5.0.1 behält sich das MSB als carry-bit, dass bekommt zog zusammen mit jeder Schicht.
Etwas störend, das Gegenteil ist NICHT wahr:-
Ich Stimme völlig mit den Menschen vor, die behaupten, dass die Vorzeichen der Operanden hat keinen Einfluss auf das Verhalten der shift-operator.
Kann jemand alle vergossen Licht auf die Spezifikation für die Posix4 Implementierung von C? Ich fühle mich, eine definitive Antwort kann dort ausruhen.
In der Zwischenzeit, es scheint, dass die einzige Lösung ist ein Konstrukt, das entlang der folgenden Zeilen;-
Dieser Werke - Leidig aber notwendig.