Die Funktion memcpy aus der Standardbibliothek (string.h) dient dem Byte-für-Byte-Kopieren eines Speicherbereichs von einem Ort zu einem anderen. Sie ist ein universelles Werkzeug zum Kopieren von Arrays, Strukturen und anderen Datenblöcken, wenn die Leistung wichtig ist und keine Typumwandlungen erforderlich sind.
Hintergrund:
memcpy wurde mit der ersten Implementierung der Standardbibliothek eingeführt, als die Notwendigkeit entstand, „rohe“ Speicherblöcke zu verarbeiten, zum Beispiel für die Arbeit mit Dateien, Netzwerkpaketen, Serialization von Daten. Ähnliche Funktionen sind in fast allen niedrig-leveligen Sprachen vorhanden.
Problem:
memcpy arbeitet nur mit Bytes, sie kümmert sich nicht um Datentypen, Ausrichtung oder überlappende Speicherbereiche. Fehlerhafte Größenangaben oder falsche Bereiche können zu Speicherbeschädigungen oder unerwarteten Ergebnissen führen. Darüber hinaus führt die Verwendung von memcpy für überlappende Bereiche zu undefiniertem Verhalten.
Lösung:
Verwenden Sie memcpy nur, wenn Sie sicher sind:
memmove.Beispielcode:
#include <string.h> typedef struct { int id; float value; } Item; Item src = {42, 3.14f}; Item dest; memcpy(&dest, &src, sizeof(Item)); // kopieren der Struktur byteweise
Wichtige Merkmale:
Kann man memcpy zum Kopieren von Strings (char) verwenden?*
Ja, nur wenn die Länge genau bekannt ist. Wenn der String null-terminiert ist, werden oft strcpy oder strncpy verwendet. Wenn die Größe verwechselt wird, kann es zu einem Überschreiten der Speicherkapazität oder dem Verlust des abschließenden Nullen kommen.
char src[] = "abc"; char dest[4]; memcpy(dest, src, 4); // 3 Buchstaben + '\0' werden kopiert
Was passiert beim Kopieren von Strukturen mit nicht-standardmäßiger Ausrichtung oder Zeigern über memcpy?
memcpy berücksichtigt weder die Semantik noch interne Zeiger. Wenn die Struktur dynamische Felder speichert (z.B. char *buf;), wird nur die Adresse selbst kopiert, nicht der Inhalt, auf den sie zeigt. Dies führt zu einer sogenannten „flachen“ Kopie.
typedef struct { char *buf; } Wrapper; Wrapper src = {malloc(10)}; Wrapper dest; memcpy(&dest, &src, sizeof(Wrapper)); // Nur das Pointer-Feld, nicht der Inhalt
Was passiert, wenn src und dest in memcpy überlappen?
Das Verhalten ist im Standard nicht definiert, es kann zu Datenverlust kommen. Für das Kopieren mit Überlappung verwenden Sie memmove:
memmove(dest, src, size); // garantiert korrektes Kopieren
Arrays überlappen: memcpy wird verwendet, um einen Teile des Arrays nach rechts zu verschieben, src und dest überschneiden sich teilweise.
Vorteile:
Nachteile:
Verwendung von memmove zur Handhabung überlappender Bereiche, das Datenvolumen wurde klar als Anzahl der Bytes in der ursprünglichen Struktur berechnet.
Vorteile:
Nachteile: