>`) in C unerwartete Ergebnisse beim Verschieben um 32 Bit erzeugen? " />
Unerwartetes Verhalten des rechten Shift-Operators (1 >> 32)
Im Bereich der Programmierung wird häufig der rechte Shift-Operator (>>) verwendet um bitweise Operationen auszuführen, insbesondere um eine Ganzzahl durch eine Zweierpotenz zu dividieren. Beim Verschieben um größere Werte kann es jedoch zu eigenartigem Verhalten kommen, wie der folgende C-Code zeigt:
int foo(int a, int b) {
return a >> b;
}
int bar(uint64_t a, int b) {
return a >> b;
}
int main() {
std::cout > 32: " > 32) > (int)32: " > (int)32) Überraschenderweise zeigt die Ausgabe dieses Programms unerwartete Ergebnisse:
foo(1, 32): 1 // Should be 0
bar(1, 32): 0
1 >> 32: 0
(int)1 >> (int)32: 0
Der Grund für diese Ergebnisse liegt in der internen Funktionsweise der CPU und des Compilers.
Verhalten der foo()-Funktion
In der Funktion foo() wird die Schiebeoperation ohne Umwandlung ausgeführt, was dazu führt, dass die CPU eine logische Rechtsverschiebung durchführt. Auf vielen Architekturen wird die logische Rechtsverschiebung als a >> (b % 32) implementiert, wodurch die oberen Bits von b praktisch ignoriert werden. Deshalb ergibt foo(1, 32) 1 >> (32 % 32), was 1 >> 0 ergibt, was 1 ergibt.
Warum ist die Umwandlung in eine 64-Bit-Ganzzahl wichtig?
In der Funktion bar() wird eine 64-Bit-Ganzzahl ohne Vorzeichen bereitgestellt, die sicherstellt, dass das Ergebnis garantiert 0 ist, da b (32) kleiner als die Anzahl der Bits im Operanden (64) ist ). Wenn b jedoch auf 64 geändert wird, wird das Ergebnis unvorhersehbar und kann immer noch 1 ergeben.
Compiler-Optimierung
Im Fall von 1 >> 32 und (int )1 >> (int)32 optimiert der Compiler diese konstanten Ausdrücke zur Kompilierungszeit. Der Standard spezifiziert undefiniertes Verhalten für Rechtsverschiebungen, bei denen die Anzahl negativ oder größer oder gleich der Länge des Operanden ist. Da 32 die Länge des Operanden überschreitet, kann der Compiler das Ergebnis nicht ermitteln und gibt 0 als sicheren Fallback aus.
CPU-spezifisches Verhalten
Die Implementierung der Rechtsverschiebung Vorgänge können je nach CPU unterschiedlich sein. Auf x86/x86-64-Architekturen beträgt die logische Rechtsverschiebung effektiv a >> (b % 32 oder 64), je nach Modus. Auf ARM-Prozessoren garantiert die richtige Shift-Operation jedoch Null für Shifts größer oder gleich 32.
Schlussfolgerung
Bei der Arbeit mit rechten Shift-Operatoren ist dies unerlässlich um mögliches undefiniertes Verhalten zu berücksichtigen, insbesondere wenn die Anzahl der Verschiebungen die Länge des Operanden überschreitet. Durch die Umwandlung in breitere Ganzzahltypen, beispielsweise 64-Bit-Ganzzahlen, können konsistente Ergebnisse über verschiedene CPUs und Compiler hinweg gewährleistet werden.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3