Linksverschiebung bei einem signed Typ führt zum Vorzeichenwechsel?
-
In meinem Buch steht folgendes:
C von A bis Z schrieb:
Mit einer Linksverschiebung (<<) werden alle Bits einer Zahl um n Stellen nach links gerückt. Die rechts entstehenden Leerstellen werden mit 0 aufgefüllt.
Achtung: Achtung bei Vorzeichen! Ist der Datentyp signed, ändert sich das Vorzeichen, wenn eine 1 in die Bitstelle des Vorzeichens gerückt wird. Falls der linke Operand aber einen negativen Wert hat, so ist das Ergebnis Compiler-spezifisch.
ich dachte der Standard legt fest, dass eine bitverschiebung nach links mit einer multiplikation mit 2 gleichzusetzen ist....?
was stimmt jetzt?
-
Sie werden es bemerkt haben, hier wurde eine Multiplikation durchgeführt. Auf diese Weise können Zahlen sehr gut potenziert werden. Die Bitstelle um eine Position nach links zu rücken, bedeutet mathematisch eine Multiplikation mit 2. Bei Einrückung um zwei Stellen nach links wird mit 4 multipliziert, bei drei mit 8, bei vier mit 16 usw. Solche Bitverschiebungen können - abhängig vom System - bis zu 40(!)-mal schneller ablaufen als normale arithmetische Berechnungen im Stil von 4*x.
mir wurde mal gesagt das multiplikationen von heutigen prozessoren genau so schnell sind wie bitshifts (weil die prozessoren auf solche operationen "extrem" optimiert sind) - naja mit dem "abhängig vom System" redet er sich gut raus
- auf meinem Toaster kann das schon sein
-
Vertexwahn schrieb:
ich dachte der Standard legt fest, dass eine bitverschiebung nach links mit einer multiplikation mit 2 gleichzusetzen ist....?
Ja, aber nur, wenn
- der linke Operand vorzeichenlos ist oder
- das (mathematische) Ergebnis der Multiplikation in dem Typ darstellbar ist.
Ansonsten hat man sogar undefiniertes Verhalten. Das heisst (auf einer 32-bit Architektur):
((signed)1) << 30 hat den Wert 2^30
((signed)1) << 31 hat undefiniertes Verhalten, die meisten Compiler werden das aber als Bitshift implementieren. Das Ergebnis ist also -2^31.
-
wenn ich jetzt code haben will der strikt konform ist darf ich dann praktisch bitshifts nur in kombination mit unsigned typen verwenden - oder?
also mit unsigned char, unsigned short, unsigned int und unsigned long (hab ich was vergessen?)
-
wenn ich jetzt code haben will der strikt konform ist darf ich dann praktisch bitshifts nur in kombination mit unsigned typen verwenden - oder?
also mit unsigned char, unsigned short, unsigned int und unsigned long (hab ich was vergessen?)nein aber durch die zweierkomplementdarstellung lässt sich ein shift nicht automatisch immer als eine multiplikation/division mit 2 auffassen sondern nur wenn das msb nicht tangiert wird... ist lediglich eine frage der interpretation hat aber nichts mit konform oder nicht konform zu tun
-
Vertexwahn schrieb:
wenn ich jetzt code haben will der strikt konform ist darf ich dann praktisch bitshifts nur in kombination mit unsigned typen verwenden - oder?
Yep, so könnte man das sehen. Wenn du signed Typen für Multiplikation und Division brauchst, dann nimm auch die * und / Operatoren. Ein Compiler wird das schon zu Shifts optimieren, wenn er das für sinnvoll hält.
-
Vertexwahn schrieb:
wenn ich jetzt code haben will der strikt konform ist darf ich dann praktisch bitshifts nur in kombination mit unsigned typen verwenden - oder?
Nein, warum? Du kannst doch dafür sorgen, dass es keine Überläufe gibt. Ist doch das gleiche Problem wie bei allen anderen arithmetischen Operationen auch, oder benutzt du jetzt + und - nur noch mit unsigned??