Shift left <<

Der Shift-Left-Operator verschiebt die Bits einer Integer-Zahl um eine gegebene Anzahl nach links und füllt die übrigen Bits mit 0 auf. Die zu verändernde Zahl steht links des Operators, die Anzahl an zu verschiebender Bit-Stellen steht rechts des Operators.












01001001100101100000001011010010
10010011001011000000010110100100
00110010110000000101101001000000
#include <stdio.h>

void printbinary(int x){
  char str[33]; str[32] = '\0';
  int i = 32;
  while(i){i--; str[i] = (x & 1) + '0'; x>>=1;}
  printf("%s\n", str);
}

int main(){
  int x = 1234567890;
  printbinary(x);
  printbinary(x << 1);
  printbinary(x << 5);
  return 0;
}

Siehe auch Shift right >>, Zuweisung <<=

In C++ wird der Shift-Left-Operator zudem oft mit der Ausgabe in einen Stream in Zusammenhang gebracht. Siehe dazu die Kommentare bei der Operatoren-Überladung weiter unten.

Details

Der Shift-Left-Operator erwartet zwei Operanden als rvalues und wird von links nach rechts abgearbeitet. Der Rückgabewert ist ein rvalue, der stets ein Integer-Typ ist.

Der Shift-Left-Operator ist nur für Integer-Werte zulässig. Unter C++ ist zusätzlich auch die Anwendung des Operators auf boolsche Werte erlaubt, welche jedoch vor Anwendung des Operators in einen int umgewandelt werden.

Durch das Verschieben der Bits nach links werden die übrigbleibenden Stellen am rechten Ende mit 0 aufgefüllt. Dies entspricht einem logischen Bitshift in Assembler. Der Shift-Left-Operator wird oftmals mittels SHL abgekürzt.

Ist die Anzahl zu verschiebender Bits negativ oder grösser als die Länge des verwendeten integer-Typs in Bits, so ist das Resultat nicht spezifiziert. Je nach Compiler können andere Resultate entstehen. In GCC beispielsweise wird die Anzahl zu verschiebender Bits als unsigned-Zahl aufgefasst und modulo der Registerbreite in Bits gerechnet, allerdings gibt der Compiler eine Warnung aus.

Die Operatoren << und >> werden hauptsächlich für low-level Programmierung verwendet, wie beispielsweise in der Systemprogrammierung. Da sie einzelne Bits verändern, wird der Umgang mit diesen Operatoren auch häufig als Bit-fiddling (Bit-Schwindeleien, auch zu verstehen als Bit-Gebastel, oder auf gut Schweizerdeutsch: Umegfätterle mit Bittli) bezeichnet. In der alltäglichen Programmierung finden diese beiden Operatoren heutzutags kaum mehr Verwendung.

Eine heute ab und zu noch anzutreffende Verwendung des Shift-Left-Operators ist die Multiplikation einer Zahl mit einer Potenz von 2. Durch die Verschiebung mit 0, 1, 2, 3, ... Bits wird der erste Operand mit 1, 2, 4, 8, ... multipliziert. In früheren Zeiten war dies die bevorzugte Art, Zahlen mit einer Potenz von 2 zu multiplizieren, da ein Bitshift vom Prozessor schneller berechnet werden konnte als eine Multiplikation. In heutigen Prozessoren spielt dies keine Rolle mehr.

42
84
168
336
  printf("%d\n", 42 << 0);
  printf("%d\n", 42 << 1);
  printf("%d\n", 42 << 2);
  printf("%d\n", 42 << 3);

Überladen des Operators

Der Shift-Left-Operator hat grundsätzlich die semantische Bedeutung einer bitweisen Verschiebung nach links. Es sei jedoch angemerkt, dass der Shift-Left-Operator mit dieser Semantik äusserst selten überladen wird. Eine sehr bekannte Überladung jedoch ist die Verwendung des Shift-Left-Operators für die Ausgabe in einen Stream.

Die Stream-Klassen in der Standardbibliothek <iostream> definieren Operatoren-Überladungen des Shift-Left-Operators, sodass dieser Operator verwendet werden kann, als würde der zweite Operand als Ausgabe in den Stream verschoben, welcher als erster Operand geschrieben wird. In C++ kann somit eine Ausgabe mittels folgendem Code erzeugt werden:





Hello world!
12345
#include <iostream>
using namespace std;

int main(){
  cout << "Hello world!" << endl;
  cout << 12345 << endl;
  return 0;
}

Für weiterführende Erklärungen über die Ein- und Ausgabe von und in Streams wird hier auf eine Dokumentation der <iostream>-Bibliothek verwiesen.

Die Prototypen für das Überladen des Shift-Left-Operators sind die folgenden (Einschränkungen und Erläuterungen siehe Überladen von Operatoren):

inside class


outside class
Type operator <<(Type);
Type operator <<(Type) const;

Type operator <<(Type, Type);

Im folgenden Beispiel wird eine Klasse für einen zweidimensionalen Vektor präsentiert. Die Überladung des Shift-Left-Operators gibt den Vektor auf dem angegebenen Stream aus. Man beachte dabei, dass hierfür eine Überladung ausserhalb der Klasse verwendet werden muss. Zudem ist es üblich, bei einer solchen Überladung den Stream als lvalue zurückzugeben, wodurch möglich wird, dass mehrere Ausgaben hintereinandergereiht werden können.



















10, 20
3, 6
10, 20; 3, 6
#include <cstdio>
#include <iostream>
using namespace std;

class Vector2{
public:
  float a[2];
  Vector2(float x, float y){a[0]=x; a[1]=y;}
};

ostream& operator <<(ostream& stream, Vector2& v){
  stream << v.a[0] << ", " << v.a[1];
  return stream;
}

int main(){
  Vector2 v1(10, 20);
  Vector2 v2(3, 6);
  cout << v1 << endl;
  cout << v2 << endl;
  cout << v1 << "; " << v2 << endl;
  return 0;
}