Nutze diese Funktion, um die binäre Schreibweise einer Variable auszugeben.
template <typename T>
void printBinary(T input) {
for (int8_t i = sizeof(input) * 8 - 1; i >= 0; i--) {
T mask = 1 << i;
if (mask & input) {
Serial.print('1');
}
else {
Serial.print('0');
}
if (i && (i % 4 == 0)) {
Serial.print(' ');
}
}
Serial.println();
}
Lass uns den Code Schritt für Schritt verstehen.
template <typename T>
Damit der Code möglichst dynamisch funktioniert und eine Funktion mehrere Datentypen handhaben kann, verwendet man ein sogenanntes "template". In diesem Fall wird der Templateparameter mit dem Namen "T" deklariert. Link
void printBinary(T input)
Hier findet die Funktionsdefinition statt. Man gibt den Datentyp der Rückgabe (void = keine Rückgabe), den Namen der Funktion (printBinary) und den Datentyp der Übergabeparameter mitsamt dem Namen (T input) an. Der Templateparameter "T" ersetzt vorerst den Datentyp, bis ein Funktionsaufruf stattfindet. Erst bei der Übergabe kann der Datentyp, der übergebenen Variable "input", dem Templateparameter "T" zugewiesen werden.
for (int8_t i = sizeof(input) * 8 - 1; i >= 0; i--)
Die for-Schleife durchläuft den Anweisungsblock von "{" bis "}", solange die Schleifenvariable "i" größer oder gleich 0 (>= 0) ist.
Nach jedem Durchlauf wird "i" um 1 dekrementiert (i--).
Der Initialwert von "i" wird auf (sizeof(input) * 8 - 1) gesetzt.
Damit entspricht er der Bitanzahl der Variable "input" (Anzahl der Bytes × 8 -1), um den höchstwertigen Bitindex korrekt darzustellen.
T mask = 1 << i
Die Variable "mask" hat denselben Datentyp wie der Templateparameter "T". In jedem Schleifendurchlauf wird der Wert "1" um "i" Bit(s) nach links verschoben (leftshift). Dadurch enthält "mask" ein einzelnes gesetztes Bit an der Position "i", während alle anderen Bits auf "0" gesetzt sind.
if (mask & input)
Bei dieser if-Anweisung wird der Code im Anweisungsblock von "{" bis "}" nur ausgeführt, wenn der bitweise AND-Operator (&) von "input" und "mask" als Ergebnis "true" ist.
else
Bei dieser else-Anweisung wird der Code im Anweisungsblock von "{" bis "}" nur ausgeführt, wenn die obere Bedingung der if-Anweisung nicht zutrifft.
if (i && (i % 4 == 0))
Bei dieser if-Anweisung wird der Code im Anweisungsblock von "{" bis "}" nur ausgeführt, wenn die Schleifenvariable "i" ungleich 0 und durch 4 teilbar ist.
Serial.print() / Serial.println()
Serial.print() gibt auf der seriellen Schnittstelle den Inhalt der Funktion print() aus.
Serial.println() gibt auf der seriellen Schnittstelle den Inhalt der Funktion println() aus und ergänzt einen Carriage-return (\r) und einen Zeilenvorschub (\n).
Beispiel - Funktionsaufruf, Verarbeitung und Ausgabe
Funktionsaufruf:
uint8_t number = 39;
printBinary(number);
Die Variable "number" mit dem Wert 39 (binär 0010 0111) wird and die Funktion printBinary() übergeben.
Verarbeitung:
template <typename T>
void printBinary(T input) {
for (int8_t i = sizeof(input) * 8 - 1; i >= 0; i--) {
T mask = 1 << i;
if (mask & input) {
Serial.print('1');
}
else {
Serial.print('0');
}
if (i && (i % 4 == 0)) {
Serial.print(' ');
}
}
Serial.println();
}
mask = 1 << i
--> erstellt eine Bitmaske, bei der nur das Bit and Position i auf 1 gesetzt ist.
Beispiel: i = 7 --> mask = 1000 0000
if (mask & input)
--> überprüft, ob das entsprechende Bit der Bitmaske in input gesetzt ist.
Wenn ja, wird "1" ausgegeben, ansonsten "0".
if (i && (i % 4 == 0)
--> fügt nach jedem vierten Bit ein Leerzeichen zur besseren Lesbarkeit ein.
Serial.println()
--> fügt am Ende einen Zeilenumbruch hinzu (\r \n).
Ausgabe (serielle Schnittstelle):
0010 0111
So wird der Wert 39 als binäre Zahl mit Vierergruppen ausgegeben.