HOWTO · Arduino

Arduino: die Funktion memset()

Mit memset() füllen Sie einen Speicherbereich in Arduino mit einem wiederholten Bytewert.

Auf dieser Seite

memset() füllt ab einer Zieladresse eine festgelegte Anzahl von Bytes mit demselben Bytewert. Mit sizeof berechnen Sie die Byteanzahl eines Arrays. Wenn Sie numerischen Array-Elementen einen Wert zuweisen möchten, verwenden Sie eine typgerechte Zuweisung.

Einführung in die Funktion memset() in Arduino

In Arduino-C++ füllt memset() einen zusammenhängenden Bytebereich mit demselben Bytewert. Die Funktion eignet sich für Bytepuffer und Zeichenarrays; sie kopiert keinen mehrbyteigen Wert in jedes Element. Das dritte Argument gibt eine Anzahl von Bytes an. Berechnen Sie sie deshalb anhand des Speicherbereichs, den Sie füllen möchten.

Die Standardfunktion ist in <string.h> deklariert und auch über den C++-Header <cstring> verfügbar. Ihr Aufruf hat die Form memset(destination, value, byte_count): destination zeigt auf das erste Byte, value wird in ein vorzeichenloses Byte umgewandelt, und byte_count gibt an, wie viele Bytes geschrieben werden. memset() wiederholt dieses umgewandelte Byte; die Bytes des ursprünglichen Werts werden nicht übernommen.

Die Funktion memset() in Arduino verwenden

Das folgende vollständige C++-Beispiel füllt ein Zeichenarray und ändert anschließend einen Teilbereich. Es verwendet die Standardausgabe, damit sich der Bytezugriff ohne eine boardspezifische serielle Verbindung zeigen lässt.

#include <cstring>
#include <iostream>

int main() {
  char letters[] = "hello";
  std::memset(letters, '.', sizeof(letters) - 1);
  std::memset(letters + 1, 'a', 2);
  std::cout << letters << '\n';
  return 0;
}
.aa..

Das Array bietet Platz für die fünf Buchstaben und das abschließende Nullzeichen. Der erste Aufruf füllt nur die fünf sichtbaren Zeichenbytes; das Nullzeichen bleibt erhalten. Der zweite Aufruf beginnt bei Index 1 und schreibt zwei Bytes, verändert also die Indizes 1 und 2. In einem Arduino-Sketch funktionieren dieselben Arrayoperationen mit memset(); mit Serial.print() können Sie das resultierende Zeichenarray ausgeben.

Leiten Sie bei Arrays mit einem anderen Elementtyp die Byteanzahl aus dem Array ab. Zum Beispiel füllt memset(values, 0, sizeof(values)) jedes Byte von values. Um einen Bereich ganzer Elemente zu füllen, verschieben Sie die Zieladresse um die Anzahl der Elemente und multiplizieren diese mit der Größe eines Elements: memset(values + start, byte_value, count * sizeof(values[0])). Arrayindizes beginnen bei null, und der ausgewählte Bereich muss innerhalb des Arrays bleiben.

Ein Integer-Array mit dem Bytewert 2 zu füllen, weist nicht jedem Element den Integerwert 2 zu. Auf einem Zielsystem mit 16-Bit-int und Little-Endian-Reihenfolge wird jedes Bytepaar zu 0x0202, was dem Wert 514 entspricht. Bei anderer Integerbreite oder Darstellung kann ein anderes Ergebnis entstehen. Wenn Sie jedem Element den typisierten Wert 2 zuweisen möchten, verwenden Sie eine Schleife wie for (int i = 0; i < count; ++i) values[i] = 2;.

Um Zeichen in einem Arduino-String zu ändern, weisen Sie sie direkt über ihre Indizes zu, zum Beispiel mit text[i] = '.';. Das ist eine direkte Zeichenzuweisung und keine Verwendung von memset().

Wichtige Hinweise

Achten Sie darauf, dass das Ziel auf beschreibbaren Speicher zeigt und die Byteanzahl in diesen Speicherbereich passt. Bei einem Array liefert sizeof(array) nur dann die gesamte Größe in Bytes, wenn der Ausdruck tatsächlich noch das Array bezeichnet. Ein Funktionsparameter, der als Array deklariert ist, ist ein Zeiger; seine Länge müssen Sie daher separat übergeben oder berechnen. Bei einer Byteanzahl von null werden keine Bytes geschrieben. Das Ziel muss dennoch ein gültiger Zeiger gemäß den Anforderungen der Funktion sein.

Ein wiederholtes Byteformat ist keine allgemeine Methode, um Werten Objekte zuzuweisen. Es eignet sich, wenn genau diese Bytebelegung beabsichtigt ist, etwa beim Füllen eines Zeichenpuffers oder beim Löschen von Bytes. Verwenden Sie es nicht zur Initialisierung nicht-trivialer C++-Objekte, insbesondere solcher, die Ressourcen verwalten oder auf Konstruktoren und Invarianten angewiesen sind. Verwenden Sie für gewöhnliche Werte und Objekte typisierte Zuweisungen, Wertinitialisierung oder die dafür vorgesehene API des Objekts.

Fazit

Verwenden Sie memset(), wenn Sie einen bekannten Bytebereich mit demselben Byte füllen müssen. Geben Sie die Größe in Bytes an, berücksichtigen Sie bei Arrays die Elementbreite und halten Sie jeden Schreibzugriff innerhalb des Zielbereichs. Für Integerwerte, Zeichenketten und Objekte sind typisierte Zuweisungen oder geeignete Initialisierungsmethoden vorzuziehen, sofern nicht ausdrücklich ein wiederholtes Byteformat benötigt wird.