HOWTO · C
Arithmetische Rechtsverschiebung in C
Erfahren Sie, wie der einzige >>-Operator in C vorzeichenlose Werte verschiebt und warum das Rechtsverschieben einer negativen vorzeichenbehafteten Ganzzahl nicht portabel ist.
Auf dieser Seite
C hat nur einen Rechtsverschiebungsoperator: >>. Er verschiebt einen ganzzahligen Wert um so viele Bitpositionen nach rechts, wie sein zweiter Operand angibt. Bei einer vorzeichenlosen Ganzzahl werden die frei werdenden höherwertigen Bits mit Nullen aufgefüllt. Das Ergebnis einer Rechtsverschiebung einer negativen vorzeichenbehafteten Ganzzahl ist nicht über alle C-Implementierungen hinweg portabel. Gehe daher nicht davon aus, dass >> immer eine arithmetische Rechtsverschiebung ausführt.
Schiebeoperatoren in C
C stellt die binären Operatoren << und >> bereit. Links steht jeweils ein ganzzahliger Wert, rechts die Anzahl der Verschiebungen. Der Ausdruck value >> count verschiebt value um count Bitpositionen nach rechts; value << count verschiebt den Wert nach links.
Zum Beispiel verschiebt value >> 1 den Wert um eine Position. Vor der Operation werden beide Operanden den Ganzzahl-Promotionen unterzogen. Daher können sich der Typ und der Wert, die tatsächlich verschoben werden, vom deklarierten Typ eines schmalen Ganzzahlobjekts unterscheiden.
Arten von Schiebeoperatoren in C
In C gibt es keine getrennten arithmetischen und logischen Rechtsverschiebungsoperatoren. Der Operator ist immer >>; das Verhalten hängt vom Typ und Wert des Operanden ab. Bei einem vorzeichenlosen Wert werden die frei werdenden höherwertigen Bits beim Verschieben nach rechts mit Nullen aufgefüllt. Bei einem nichtnegativen vorzeichenbehafteten Wert liefert die Rechtsverschiebung dasselbe Ergebnis wie die Division durch die entsprechende Zweierpotenz.
Die Rechtsverschiebung einer negativen vorzeichenbehafteten Ganzzahl ist nicht portabel. Implementierungen können sie unterschiedlich behandeln. Daher ist es kein verlässliches Verhalten für portablen Code, wenn das Vorzeichenbit übernommen wird. Die Bezeichnung „arithmetische Rechtsverschiebung“ meint deshalb ein Verhalten, das bei manchen Implementierungen vorkommt, und keinen zweiten C-Operator. Wenn dein Programm von diesem Verhalten abhängt, dokumentiere die Annahmen zu Compiler und Zielplattform.
Führe dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <stdio.h>
int main(void) {
unsigned int value = 15u;
int signed_value = -15;
printf("unsigned: %u >> 1 = %u\n", value, value >> 1);
printf("signed value: %d\n", signed_value);
return 0;
}
unsigned: 15 >> 1 = 7
signed value: -15
Im unveränderten Ausgabeblock sind die Beschriftungen „unsigned“ und „signed value“ auf Englisch; sie bleiben dort unverändert. Der Block stellt einen vorzeichenlosen Wert einem negativen vorzeichenbehafteten Wert gegenüber. Der Code gibt den negativen vorzeichenbehafteten Wert aus, verschiebt ihn aber nicht nach rechts und macht daher keine Aussage über das Ergebnis einer solchen Verschiebung.
Die Analogie zur Division ist begrenzt: Sie ist für vorzeichenlose und nichtnegative vorzeichenbehaftete Werte hilfreich, macht die Rechtsverschiebung einer negativen vorzeichenbehafteten Ganzzahl aber nicht portabel. Außerdem muss die Anzahl der Verschiebungen nichtnegativ und kleiner als die Breite des promovierten linken Operanden sein. Andernfalls ist das Verhalten undefiniert. Gehe auch nicht davon aus, dass eine Linksverschiebung immer einer Multiplikation mit einer Zweierpotenz entspricht: Ein Überlauf bei einem vorzeichenbehafteten Wert kann auch diese Operation undefiniert machen.
Fazit
C verwendet nur einen Operator für die Rechtsverschiebung: >>. Bei vorzeichenlosen Werten ist das Auffüllen mit Nullen festgelegt; das Ergebnis einer Rechtsverschiebung einer negativen vorzeichenbehafteten Ganzzahl ist dagegen nicht portabel. Verwende vorzeichenlose Werte, wenn du vorhersagbare bitweise Rechtsverschiebungen benötigst. Verlasse dich auf ein bestimmtes Verhalten bei vorzeichenbehafteten Werten nur, wenn deine Anforderungen an die Implementierung es ausdrücklich zulassen.