Faszinierendes Verhalten des Rechtsverschiebungsoperators
Der Rechtsverschiebungsoperator (>>) zeigt ein eigenartiges Verhalten beim Umgang mit großen Rechtsverschiebungswerten . Betrachten Sie das folgende Programm:
<code class="c++">#include <iostream> #include <stdint.h> int foo(int a, int b) { return a >> b; } int bar(uint64_t a, int b) { return a >> b; } int main() { std::cout << "foo(1, 32): " << foo(1, 32) << std::endl; std::cout << "bar(1, 32): " << bar(1, 32) << std::endl; std::cout << "1 >> 32: " << (1 >> 32) << std::endl; //warning std::cout << "(int)1 >> (int)32: " << ((int)1 >> (int)32) << std::endl; //warning }
Die erwartete Ausgabe für foo(1, 32) wäre 0, aber überraschenderweise gibt es 1 zurück. Dies kann auf Folgendes zurückgeführt werden:
Logische Verschiebung vs. arithmetische Verschiebung
Auf x86/x86-64-Architekturen führt der Rechtsverschiebungsoperator tatsächlich eine logische Rechtsverschiebung durch, was bedeutet, dass er die frei gewordenen Stellen füllt Bits mit 0, unabhängig vom Vorzeichen des linken Operanden. Das Verhalten ähnelt der Verwendung eines >>> b.
Compiler-Optimierung
Im Fall von foo(1, 32) wird der Wert 32 in int umgewandelt, was effektiv auf 32 Bits gekürzt wird. Da der maximale Wert, den ein int halten kann, 231-1 beträgt, ist die Rechtsverschiebung im Wesentlichen ein >>> (32 % 32), was 0 ergibt.
Undefiniertes Verhalten
Der relevante C-Standard besagt, dass „das Verhalten undefiniert ist“ für Rechtsverschiebungen mit einer größeren Anzahl größer oder gleich der Breite des heraufgestuften linken Operanden. In diesem Fall sind beide 1 >> 32 und (int)1 >> (int)32 haben eine Anzahl größer als 32, was zu unvorhersehbaren Ergebnissen führt.
Unterschied zu bar(1, 32)
Die Funktionsleiste benötigt 64-Bit Ganzzahl ohne Vorzeichen, die garantiert eine Breite größer als 32 hat. Daher wird die Rechtsverschiebung im Balken nicht durch undefiniertes Verhalten beeinflusst.
Schlussfolgerung
Das Verhalten von Der Rechtsverschiebungsoperator wird bei großen Verschiebungswerten mehrdeutig. Auf x86/x86-64-Architekturen wird eine logische Rechtsverschiebung durchgeführt, während auf ARM möglicherweise eine andere Implementierung verwendet wird. Aufgrund undefinierten Verhaltens sollte das Ergebnis von Rechtsverschiebungen mit einer Anzahl größer oder gleich der Breite des Operanden in portablem Code vermieden werden.
Das obige ist der detaillierte Inhalt von## Warum zeigt der rechte Shift-Operator bei großen Shift-Werten unerwartetes Verhalten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!